-
-
- -
- -
- -
- -
- -
- -
- -
- -
- -
-
-
- -
- -
-
这是一张图片
-photo Share A
-- -
这是一段视频
-Text Share B
-- -
这是一篇文章
-Text Share C
-- - - - \ No newline at end of file diff --git a/trustie2/Gemfile b/trustie2/Gemfile deleted file mode 100644 index eab64e04d..000000000 --- a/trustie2/Gemfile +++ /dev/null @@ -1,89 +0,0 @@ -#source 'http://ruby.taobao.org/' -source 'https://rubygems.org' - -unless RUBY_PLATFORM =~ /w32/ - # unix-like only - gem 'iconv' - gem 'rubyzip' - gem 'zip-zip' -end -platforms :ruby do - group :production do - gem "puma" - end -end -gem 'seems_rateable', path: 'lib/seems_rateable' -gem "rails", "3.2.13" -gem "jquery-rails", "~> 2.0.2" -gem "i18n", "~> 0.6.0" -gem "coderay", "~> 1.0.6" -gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] -gem "builder", "3.0.0" -gem 'acts-as-taggable-on', '2.4.1' -gem 'sunspot_rails', '2.2.0' -gem 'sunspot_solr', '2.2.0' -gem 'will_paginate', '~> 3.0' -gem 'progress_bar' -gem 'nokogiri', "~> 1.6.0" - -gem 'ox' # For faster XML Parsing, use Ox or Nokogiri. Ox has highest priority if available. -#gem 'nokogiri' # For faster XML Parsing. If neither Ox nor Nokogiri available, we'll fall back to REXML. -gem 'httpclient' # Absolutely necessary for soap4r-ng. Net::HTTP Fallback is quite broken, so don't let that happen. -gem 'soap4r-ng' - -# Gems used only for assets and not required -# in production environments by default. -group :assets do - gem 'sass-rails', '~> 3.2.3' - gem 'coffee-rails', '~> 3.2.1' - - # See https://github.com/sstephenson/execjs#readme for more supported runtimes - # gem 'therubyracer', :platforms => :ruby - - gem 'uglifier', '>= 1.0.3' -end - -# Optional gem for LDAP authentication -group :ldap do - gem "net-ldap", "~> 0.3.1" -end - -# Optional gem for OpenID authentication -group :openid do - gem "ruby-openid", "~> 2.1.4", :require => "openid" - gem "rack-openid" -end - -# Optional gem for exporting the gantt to a PNG file, not supported with jruby -platforms :jruby do - # jruby-openssl is bundled with JRuby 1.7.0 - gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0' - gem "activerecord-jdbc-adapter", "1.2.5" -end - -# Include database gems for the adapters found in the database -# configuration file -gem "mysql2", "~> 0.3.11", :platforms => [:mri, :mingw] -gem "activerecord-jdbcmysql-adapter", :platforms => :jruby - - -group :development do - gem "rdoc", ">= 2.4.2" - if nil - gem 'thin' - gem 'rack-mini-profiler' - end -end - - -local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local") -if File.exists?(local_gemfile) - puts "Loading Gemfile.local ..." if $DEBUG # `ruby -d` or `bundle -v` - instance_eval File.read(local_gemfile) -end - -# Load plugins' Gemfiles -Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file| - puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v` - instance_eval File.read(file) -end diff --git a/trustie2/README.rdoc b/trustie2/README.rdoc deleted file mode 100644 index 4132fb86e..000000000 --- a/trustie2/README.rdoc +++ /dev/null @@ -1,5 +0,0 @@ -= Redmine - -Redmine is a flexible project management web application written using Ruby on Rails framework. - -More details can be found in the doc directory or on the official website http://www.redmine.org diff --git a/trustie2/Rakefile b/trustie2/Rakefile deleted file mode 100644 index 5fbdf84ca..000000000 --- a/trustie2/Rakefile +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env rake -# Add your own tasks in files placed in lib/tasks ending in .rake, -# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. - -require File.expand_path('../config/application', __FILE__) - -RedmineApp::Application.load_tasks diff --git a/trustie2/ReadMe.txt b/trustie2/ReadMe.txt deleted file mode 100644 index e7444a6c5..000000000 --- a/trustie2/ReadMe.txt +++ /dev/null @@ -1,40 +0,0 @@ -patch: -ûIJ֣issues#655 -Ϊķ -alias - ֮ǰʾ ֮ -name firstname+lastname login -nickname xxx login -realname xxx firstname+lastname -================================================================================ -app/models/setting.rb :165 - # fixed domain url in development. tantantan's bug - if Rails.env.development? - methods.map do |m| - define_singleton_method m do; nil; end if m.to_s =~ /([a-zA-Z]+_domain)$/ - end - end - ƶsubdomainʹڶת - Ϊ˿㣬ʹ֮developmentģʽʧЧ - # => nyan -================================================================================ -app/controller/projects_controller.rb ===> projects#fake - fake filter: ˴ҳеCount - Ϊȷɾfake -================================================================================ -#ƥʾı -app\helper\application_helper.rb -# rewrite navigation - -app\views\layouts\_base_header.html.erb -# reset navigation by domain name and url through regular match -================================================================================ -#ҳƥ벻ͬҳ -app\controller\welcome_controller.rb - def entry_select_user - if request.original_url.match(/user\.trustie\.net/) - redirect_to(:controller => "users", :action => "index") - return 0 - end - end -================================================================================ \ No newline at end of file diff --git a/trustie2/app/.DS_Store b/trustie2/app/.DS_Store deleted file mode 100644 index 9d17f8cfc..000000000 Binary files a/trustie2/app/.DS_Store and /dev/null differ diff --git a/trustie2/app/assets/.DS_Store b/trustie2/app/assets/.DS_Store deleted file mode 100644 index 750354617..000000000 Binary files a/trustie2/app/assets/.DS_Store and /dev/null differ diff --git a/trustie2/app/assets/javascripts/.DS_Store b/trustie2/app/assets/javascripts/.DS_Store deleted file mode 100644 index 0b47a3d2c..000000000 Binary files a/trustie2/app/assets/javascripts/.DS_Store and /dev/null differ diff --git a/trustie2/app/assets/javascripts/apply_project_masters.js b/trustie2/app/assets/javascripts/apply_project_masters.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/apply_project_masters.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/forums.js b/trustie2/app/assets/javascripts/forums.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/forums.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/memos.js b/trustie2/app/assets/javascripts/memos.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/memos.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/no_uses.js b/trustie2/app/assets/javascripts/no_uses.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/no_uses.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/open_source_projects.js b/trustie2/app/assets/javascripts/open_source_projects.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/open_source_projects.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/ossean_highcharts.js.coffee b/trustie2/app/assets/javascripts/ossean_highcharts.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/trustie2/app/assets/javascripts/ossean_highcharts.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/trustie2/app/assets/javascripts/ossean_monitors.js.coffee b/trustie2/app/assets/javascripts/ossean_monitors.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/trustie2/app/assets/javascripts/ossean_monitors.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/trustie2/app/assets/javascripts/ossean_sta_git_matchs.js.coffee b/trustie2/app/assets/javascripts/ossean_sta_git_matchs.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/trustie2/app/assets/javascripts/ossean_sta_git_matchs.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/trustie2/app/assets/javascripts/praise_tread.js b/trustie2/app/assets/javascripts/praise_tread.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/praise_tread.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/relative_bugs.js.coffee b/trustie2/app/assets/javascripts/relative_bugs.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/trustie2/app/assets/javascripts/relative_bugs.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/trustie2/app/assets/javascripts/relative_memos.js.coffee b/trustie2/app/assets/javascripts/relative_memos.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/trustie2/app/assets/javascripts/relative_memos.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/trustie2/app/assets/javascripts/school.js b/trustie2/app/assets/javascripts/school.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/school.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/shares.js b/trustie2/app/assets/javascripts/shares.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/shares.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/softapplications.js b/trustie2/app/assets/javascripts/softapplications.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/softapplications.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/teachers.js b/trustie2/app/assets/javascripts/teachers.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/teachers.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/javascripts/user_traces.js.coffee b/trustie2/app/assets/javascripts/user_traces.js.coffee deleted file mode 100644 index 761567942..000000000 --- a/trustie2/app/assets/javascripts/user_traces.js.coffee +++ /dev/null @@ -1,3 +0,0 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/trustie2/app/assets/javascripts/zipdown.js b/trustie2/app/assets/javascripts/zipdown.js deleted file mode 100644 index dee720fac..000000000 --- a/trustie2/app/assets/javascripts/zipdown.js +++ /dev/null @@ -1,2 +0,0 @@ -// Place all the behaviors and hooks related to the matching controller here. -// All this logic will automatically be available in application.js. diff --git a/trustie2/app/assets/stylesheets/apply_project_masters.css b/trustie2/app/assets/stylesheets/apply_project_masters.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/apply_project_masters.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/forums.css b/trustie2/app/assets/stylesheets/forums.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/forums.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/memos.css b/trustie2/app/assets/stylesheets/memos.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/memos.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/no_uses.css b/trustie2/app/assets/stylesheets/no_uses.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/no_uses.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/open_source_projects.css b/trustie2/app/assets/stylesheets/open_source_projects.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/open_source_projects.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/ossean_highcharts.css.scss b/trustie2/app/assets/stylesheets/ossean_highcharts.css.scss deleted file mode 100644 index 10f479b5b..000000000 --- a/trustie2/app/assets/stylesheets/ossean_highcharts.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the ossean_highcharts controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/trustie2/app/assets/stylesheets/ossean_monitors.css.scss b/trustie2/app/assets/stylesheets/ossean_monitors.css.scss deleted file mode 100644 index 361b1a2f8..000000000 --- a/trustie2/app/assets/stylesheets/ossean_monitors.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the ossean_monitors controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/trustie2/app/assets/stylesheets/ossean_sta_git_matchs.css.scss b/trustie2/app/assets/stylesheets/ossean_sta_git_matchs.css.scss deleted file mode 100644 index b5e1d6456..000000000 --- a/trustie2/app/assets/stylesheets/ossean_sta_git_matchs.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the ossean_sta_git_matchs controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/trustie2/app/assets/stylesheets/praise_tread.css b/trustie2/app/assets/stylesheets/praise_tread.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/praise_tread.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/relative_bugs.css.scss b/trustie2/app/assets/stylesheets/relative_bugs.css.scss deleted file mode 100644 index 7bf09c39c..000000000 --- a/trustie2/app/assets/stylesheets/relative_bugs.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the RelativeBugs controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/trustie2/app/assets/stylesheets/relative_memos.css.scss b/trustie2/app/assets/stylesheets/relative_memos.css.scss deleted file mode 100644 index 542946ea6..000000000 --- a/trustie2/app/assets/stylesheets/relative_memos.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the RelativeMemos controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/trustie2/app/assets/stylesheets/scaffold.css b/trustie2/app/assets/stylesheets/scaffold.css deleted file mode 100644 index 1ae700029..000000000 --- a/trustie2/app/assets/stylesheets/scaffold.css +++ /dev/null @@ -1,56 +0,0 @@ -body { background-color: #fff; color: #333; } - -body, p, ol, ul, td { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 13px; - line-height: 18px; -} - -pre { - background-color: #eee; - padding: 10px; - font-size: 11px; -} - -a { color: #000; } -a:visited { color: #666; } -a:hover { color: #fff; background-color:#000; } - -div.field, div.actions { - margin-bottom: 10px; -} - -#notice { - color: green; -} - -.field_with_errors { - padding: 2px; - background-color: red; - display: table; -} - -#error_explanation { - width: 450px; - border: 2px solid red; - padding: 7px; - padding-bottom: 0; - margin-bottom: 20px; - background-color: #f0f0f0; -} - -#error_explanation h2 { - text-align: left; - font-weight: bold; - padding: 5px 5px 5px 15px; - font-size: 12px; - margin: -7px; - margin-bottom: 0px; - background-color: #c00; - color: #fff; -} - -#error_explanation ul li { - font-size: 12px; - list-style: square; -} diff --git a/trustie2/app/assets/stylesheets/school.css b/trustie2/app/assets/stylesheets/school.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/school.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/shares.css b/trustie2/app/assets/stylesheets/shares.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/shares.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/softapplications.css b/trustie2/app/assets/stylesheets/softapplications.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/softapplications.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/teachers.css b/trustie2/app/assets/stylesheets/teachers.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/teachers.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/assets/stylesheets/user_traces.css.scss b/trustie2/app/assets/stylesheets/user_traces.css.scss deleted file mode 100644 index 686b72667..000000000 --- a/trustie2/app/assets/stylesheets/user_traces.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the user_traces controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/trustie2/app/assets/stylesheets/zipdown.css b/trustie2/app/assets/stylesheets/zipdown.css deleted file mode 100644 index afad32db0..000000000 --- a/trustie2/app/assets/stylesheets/zipdown.css +++ /dev/null @@ -1,4 +0,0 @@ -/* - Place all the styles related to the matching controller here. - They will automatically be included in application.css. -*/ diff --git a/trustie2/app/controllers/application_controller.rb b/trustie2/app/controllers/application_controller.rb deleted file mode 100644 index 3227a1491..000000000 --- a/trustie2/app/controllers/application_controller.rb +++ /dev/null @@ -1,804 +0,0 @@ -#!/bin/env ruby -# encoding: utf-8 -# Redmine - project management software -# Copyright (C) 2006-2013 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 'uri' -require 'cgi' - -class Unauthorized < Exception; end - -class ApplicationController < ActionController::Base - include Redmine::I18n - include Redmine::Pagination - include RoutesHelper - helper :routes - - #added by william - helper :watchers - - class_attribute :accept_api_auth_actions - class_attribute :accept_rss_auth_actions - class_attribute :model_object - - layout 'base' - - protect_from_forgery - def handle_unverified_request - super - cookies.delete(autologin_cookie_name) - end - - before_filter :user_agent - - rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token - rescue_from ::Unauthorized, :with => :deny_access - rescue_from ::ActionView::MissingTemplate, :with => :missing_template - - include Redmine::Search::Controller - include Redmine::MenuManager::MenuController - helper Redmine::MenuManager::MenuHelper - - def user_agent - logger.info "HTTP_USER_AGENT #{request.env["HTTP_USER_AGENT"]}" - end - - def session_expiration - if session[:user_id] - if session_expired? && !try_to_autologin - reset_session - flash[:error] = l(:error_session_expired) - redirect_to signin_url - else - session[:atime] = Time.now.utc.to_i - end - end - end - - - def session_expired? - if Setting.session_lifetime? - unless session[:ctime] && (Time.now.utc.to_i - session[:ctime].to_i <= Setting.session_lifetime.to_i * 60) - return true - end - end - if Setting.session_timeout? - unless session[:atime] && (Time.now.utc.to_i - session[:atime].to_i <= Setting.session_timeout.to_i * 60) - return true - end - end - false - end - - def start_user_session(user) - session[:user_id] = user.id - session[:ctime] = Time.now.utc.to_i - session[:atime] = Time.now.utc.to_i - end - - # Returns the current user or nil if no user is logged in - # and starts a session if needed - def current_user - find_current_user - end - def find_current_user - user = nil - unless api_request? - if session[:user_id] - # existing session - user = (User.active.find(session[:user_id]) rescue nil) - elsif autologin_user = try_to_autologin - user = autologin_user - elsif params[:format] == 'atom' && params[:key] && request.get? && accept_rss_auth? - # RSS key authentication does not start a session - user = User.find_by_rss_key(params[:key]) - end - end - if user.nil? && Setting.rest_api_enabled? && accept_api_auth? - if (key = api_key_from_request) - # Use API key - user = User.find_by_api_key(key) - else - # HTTP Basic, either username/password or API key/random - authenticate_with_http_basic do |username, password| - user = User.try_to_login(username, password) || User.find_by_api_key(username) - end - end - # Switch user if requested by an admin user - if user && user.admin? && (username = api_switch_user_from_request) - su = User.find_by_login(username) - if su && su.active? - logger.info(" User switched by: #{user.login} (id=#{user.id})") if logger - user = su - else - render_error :message => 'Invalid X-Redmine-Switch-User header', :status => 412 - end - end - end - user - end - - def autologin_cookie_name - Redmine::Configuration['autologin_cookie_name'].presence || 'autologin' - end - - def try_to_autologin - if cookies[autologin_cookie_name] && Setting.autologin? - # auto-login feature starts a new session - user = User.try_to_autologin(cookies[autologin_cookie_name]) - if user - reset_session - start_user_session(user) - end - user - end - end - - # Sets the logged in user - def logged_user=(user) - reset_session - if user && user.is_a?(User) - User.current = user - start_user_session(user) - else - User.current = User.anonymous - end - end - - def set_localization - lang = nil - if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE'] - accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first - if !accept_lang.blank? - accept_lang = accept_lang.downcase - lang = find_language(accept_lang) || find_language(accept_lang.split('-').first) - end - end - lang ||= Setting.default_language - set_language_if_valid(lang) - end - - def require_admin - return unless require_login - if !User.current.admin? - render_403 - return false - end - true - end - - # Authorize the user for the requested action - def authorize(ctrl = params[:controller], action = params[:action], global = false) - allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project || @projects, :global => global) - if allowed - true - else - if @project && @project.archived? - render_403 :message => :notice_not_authorized_archived_project - else - deny_access - end - end - end - - # Authorize the user for the requested action outside a project - def authorize_global(ctrl = params[:controller], action = params[:action], global = true) - authorize(ctrl, action, global) - end - - # Find project of id params[:id] - def find_project - @project = Project.find(params[:id]) - rescue ActiveRecord::RecordNotFound - render_404 - end - - # Find project of id params[:project_id] - def find_project_by_project_id - @project = Project.find(params[:project_id]) - rescue ActiveRecord::RecordNotFound - render_404 - end - - # Find a project based on params[:project_id] - # TODO: some subclasses override this, see about merging their logic - def find_optional_project - @project = Project.find(params[:project_id]) unless params[:project_id].blank? - allowed = User.current.allowed_to?({:controller => params[:controller], :action => params[:action]}, @project, :global => true) - allowed ? true : deny_access - rescue ActiveRecord::RecordNotFound - render_404 - end - - # Finds and sets @project based on @object.project - def find_project_from_association - render_404 unless @object.present? - - @project = @object.project - end - - def find_model_object - model = self.class.model_object - if model - @object = model.find(params[:id]) - self.instance_variable_set('@' + controller_name.singularize, @object) if @object - end - rescue ActiveRecord::RecordNotFound - render_404 - end - - def self.model_object(model) - self.model_object = model - end - - # Find the issue whose id is the :id parameter - # Raises a Unauthorized exception if the issue is not visible - def find_issue - # Issue.visible.find(...) can not be used to redirect user to the login form - # if the issue actually exists but requires authentication - @issue = Issue.find(params[:id]) - raise Unauthorized unless @issue.visible? - @project = @issue.project - rescue ActiveRecord::RecordNotFound - render_404 - end - - # Find issues with a single :id param or :ids array param - # Raises a Unauthorized exception if one of the issues is not visible - def find_issues - @issues = Issue.find_all_by_id(params[:id] || params[:ids]) - raise ActiveRecord::RecordNotFound if @issues.empty? - raise Unauthorized unless @issues.all?(&:visible?) - @projects = @issues.collect(&:project).compact.uniq - @project = @projects.first if @projects.size == 1 - rescue ActiveRecord::RecordNotFound - render_404 - end - - # make sure that the user is a member of the project (or admin) if project is private - # used as a before_filter for actions that do not require any particular permission on the project - def check_project_privacy - if @project && !@project.archived? - if @project.visible? - true - else - deny_access - end - else - @project = nil - render_404 - false - end - end - - def back_url - url = params[:back_url] - if url.nil? && referer = request.env['HTTP_REFERER'] - url = CGI.unescape(referer.to_s) - end - url - end - - def redirect_back_or_default(default, options={}) - back_url = params[:back_url].to_s - if back_url.present? - begin - 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)}) - redirect_to(back_url) - return - end - rescue URI::InvalidURIError - logger.warn("Could not redirect to invalid URL #{back_url}") - # redirect to default - end - elsif options[:referer] - redirect_to_referer_or default - return - end - redirect_to default - false - end - - # Redirects to the request referer if present, redirects to args or call block otherwise. - def redirect_to_referer_or(*args, &block) - redirect_to :back - rescue ::ActionController::RedirectBackError - if args.any? - redirect_to *args - elsif block_given? - block.call - else - raise "#redirect_to_referer_or takes arguments or a block" - end - end - - def render_403(options={}) - @project = nil - render_error({:message => :notice_not_authorized, :status => 403}.merge(options)) - return false - end - - def render_404(options={}) - render_error({:message => :notice_file_not_found, :status => 404}.merge(options)) - return false - end - - # Renders an error response - def render_error(arg) - arg = {:message => arg} unless arg.is_a?(Hash) - - @message = arg[:message] - @message = l(@message) if @message.is_a?(Symbol) - @status = arg[:status] || 500 - - respond_to do |format| - format.html { - render :template => 'common/error', :layout => use_layout, :status => @status - } - format.any { head @status } - end - end - - # Handler for ActionView::MissingTemplate exception - def missing_template - logger.warn "Missing template, responding with 404" - @project = nil - render_404 - end - - # Picks which layout to use based on the request - # - # @return [boolean, string] name of the layout to use or false for no layout - def use_layout - request.xhr? ? false : 'base' - end - - def invalid_authenticity_token - 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." - end - - def render_feed(items, options={}) - @items = items || [] - @items.sort! {|x,y| y.event_datetime <=> x.event_datetime } - @items = @items.slice(0, Setting.feeds_limit.to_i) - @title = options[:title] || Setting.app_title - render :template => "common/feed", :formats => [:atom], :layout => false, - :content_type => 'application/atom+xml' - end - - def self.accept_rss_auth(*actions) - if actions.any? - self.accept_rss_auth_actions = actions - else - self.accept_rss_auth_actions || [] - end - end - - def accept_rss_auth?(action=action_name) - self.class.accept_rss_auth.include?(action.to_sym) - end - - def self.accept_api_auth(*actions) - if actions.any? - self.accept_api_auth_actions = actions - else - self.accept_api_auth_actions || [] - end - end - - def accept_api_auth?(action=action_name) - self.class.accept_api_auth.include?(action.to_sym) - end - - # Returns the number of objects that should be displayed - # on the paginated list - def per_page_option - per_page = nil - if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i) - per_page = params[:per_page].to_s.to_i - session[:per_page] = per_page - elsif session[:per_page] - per_page = session[:per_page] - else - per_page = Setting.per_page_options_array.first || 25 - end - per_page - end - - # Returns offset and limit used to retrieve objects - # for an API response based on offset, limit and page parameters - def api_offset_and_limit(options=params) - if options[:offset].present? - offset = options[:offset].to_i - if offset < 0 - offset = 0 - end - end - limit = options[:limit].to_i - if limit < 1 - limit = 25 - elsif limit > 100 - limit = 100 - end - if offset.nil? && options[:page].present? - offset = (options[:page].to_i - 1) * limit - offset = 0 if offset < 0 - offset ||= 0 - end - - - [offset, limit] - end - - # qvalues http header parser - # code taken from webrick - def parse_qvalues(value) - tmp = [] - if value - parts = value.split(/,\s*/) - parts.each {|part| - if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part) - val = m[1] - q = (m[2] or 1).to_f - tmp.push([val, q]) - end - } - tmp = tmp.sort_by{|val, q| -q} - tmp.collect!{|val, q| val} - end - return tmp - rescue - nil - end - - # Returns a string that can be used as filename value in Content-Disposition header - def filename_for_content_disposition(name) - request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name - end - - def api_request? - %w(xml json).include? params[:format] - end - - # Returns the API key present in the request - def api_key_from_request - if params[:key].present? - params[:key].to_s - elsif request.headers["X-Redmine-API-Key"].present? - request.headers["X-Redmine-API-Key"].to_s - end - end - - # Returns the API 'switch user' value if present - def api_switch_user_from_request - request.headers["X-Redmine-Switch-User"].to_s.presence - end - - # Sets the `flash` notice or error based the number of issues that did not save - # - # @param [Array, Issue] issues all of the saved and unsaved Issues - # @param [Array, Integer] unsaved_issue_ids the issue ids that were not saved - def set_flash_from_bulk_issue_save(issues, unsaved_issue_ids) - if unsaved_issue_ids.empty? - flash[:notice] = l(:notice_successful_update) unless issues.empty? - else - flash[:error] = l(:notice_failed_to_save_issues, - :count => unsaved_issue_ids.size, - :total => issues.size, - :ids => '#' + unsaved_issue_ids.join(', #')) - end - end - - # Rescues an invalid query statement. Just in case... - def query_statement_invalid(exception) - logger.error "Query::StatementInvalid: #{exception.message}" if logger - session.delete(:query) - sort_clear if respond_to?(:sort_clear) - render_error "An error occurred while executing the query and has been logged. Please report this error to your Redmine administrator." - end - - # Renders a 200 response for successfull updates or deletions via the API - def render_api_ok - render_api_head :ok - end - - # Renders a head API response - def render_api_head(status) - # #head would return a response body with one space - render :text => '', :status => status, :layout => nil - end - - # Renders API response on validation failure - def render_validation_errors(objects) - if objects.is_a?(Array) - @error_messages = objects.map {|object| object.errors.full_messages}.flatten - else - @error_messages = objects.errors.full_messages - end - render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => nil - end - - # Overrides #_include_layout? so that #render with no arguments - # doesn't use the layout for api requests - def _include_layout?(*args) - api_request? ? false : super - end - - ## Please added code in html. - #
").html_safe - end - - def format_version_name(version) - if version.project == @project - h(version) - else - h("#{version.project} - #{version}") - end - end - - def due_date_distance_in_words(date) - if date - l((date < Date.today ? :label_roadmap_overdue : :label_roadmap_due_in), distance_of_date_in_words(Date.today, date)) - end - end - - # Renders a tree of projects 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) - #Modified by nie. - def render_project_nested_lists(projects) - s = '' - if projects.any? - ancestors = [] - original_project = @project - #modified by nie - projects.each do |project| - # set the project environment to please macros. - @project = project - if (ancestors.empty? || project.is_descendant_of?(ancestors.last)) -# s << "
- \n"
- s << "
- " - if project.try(:project_type) == Project::ProjectType_project - s << h(block_given? ? yield(project) : project.name) - else - end - - if project.try(:project_type) == Project::ProjectType_project - unless User.current.member_of?(@project) - s << "" - s << watcher_link(@project, User.current) #, ['whiteButton']) - s << "" - end - s << (render :partial => 'projects/project', :locals => {:project => project}).to_s - else - s << (render :partial => 'projects/course', :locals => {:project => project}).to_s - end - s << "\n" - ancestors << project - end - s << ("
- \n"
- else
- ancestors.pop
- s << ""
- while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
- ancestors.pop
- s << "
- \n"
- s << "
- \n"
- else
- ancestors.pop
- s << ""
- while (ancestors.any? && !project.is_descendant_of?(ancestors.last))
- ancestors.pop
- s << "
- \n"
- pages[node].each do |page|
- content << "
- " - content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'show', :project_id => page.project, :id => page.title, :version => nil}, - :title => (options[:timestamp] && page.updated_on ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil)) - content << "\n" + render_page_hierarchy(pages, page.id, options) if pages[page.id] - content << " \n" - end - content << "
'.html_safe + l(:label_export_to)) - yield Redmine::Views::OtherFormatsBuilder.new(self) - concat('
'.html_safe) - end - - def page_header_title - if @project.nil? || @project.new_record? - h(Setting.app_title) - else - 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 << "\xe2\x80\xa6" - ancestors = ancestors[-2, 2] - end - b += ancestors.collect { |p| link_to_project(p, {:jump => current_menu_item}, :class => 'ancestor') } - end - b << h(@project) - b.join(" \xc2\xbb ").html_safe - end - end - - def html_title(*args) - if args.empty? - title = @html_title || [] - title << @open_source_project.name if @open_source_project - title << Setting.app_title unless Setting.app_title == title.last - title.select { |t| !t.blank? }.join(' - ') - else - @html_title ||= [] - @html_title += args - end - end - - # Returns the theme, controller name, and action as css classes for the - # HTML body. - def body_css_classes - css = [] - if theme = Redmine::Themes.theme(Setting.ui_theme) - css << 'theme-' + theme.name - end - - css << 'controller-' + controller_name - css << 'action-' + action_name - css.join(' ') - end - - def accesskey(s) - @used_accesskeys ||= [] - key = Redmine::AccessKeys.key_for(s) - return nil if @used_accesskeys.include?(key) - @used_accesskeys << key - key - end - - - def parse_non_pre_blocks(text, obj, macros) - s = StringScanner.new(text) - tags = [] - parsed = '' - while !s.eos? - s.scan(/(.*?)(<(\/)?(pre|code)(.*?)>|\z)/im) - text, full_tag, closing, tag = s[1], s[2], s[3], s[4] - if tags.empty? - yield text - inject_macros(text, obj, macros) if macros.any? - else - inject_macros(text, obj, macros, false) if macros.any? - end - parsed << text - if tag - if closing - if tags.last == tag.downcase - tags.pop - end - else - tags << tag.downcase - end - parsed << full_tag - end - end - # Close any non closing tags - while tag = tags.pop - parsed << "#{tag}>" - end - parsed - end - - - # Wiki links - # - # Examples: - # [[mypage]] - # [[mypage|mytext]] - # wiki links can refer other project wikis, using project name or identifier: - # [[project:]] -> wiki starting page - # [[project:|mytext]] - # [[project:mypage]] - # [[project:mypage|mytext]] - def parse_wiki_links(text, project, obj, attr, only_path, options) - text.gsub!(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m| - link_project = project - esc, all, page, title = $1, $2, $3, $5 - if esc.nil? - if page =~ /^([^\:]+)\:(.*)$/ - identifier, page = $1, $2 - link_project = Project.find_by_identifier(identifier) || Project.find_by_name(identifier) - title ||= identifier if page.blank? - end - - if link_project && link_project.wiki - # extract anchor - anchor = nil - if page =~ /^(.+?)\#(.+)$/ - page, anchor = $1, $2 - end - anchor = sanitize_anchor_name(anchor) if anchor.present? - # check if page exists - wiki_page = link_project.wiki.find_page(page) - url = if anchor.present? && wiki_page.present? && (obj.is_a?(WikiContent) || obj.is_a?(WikiContent::Version)) && obj.page == wiki_page - "##{anchor}" - else - case options[:wiki_links] - when :local; - "#{page.present? ? Wiki.titleize(page) : ''}.html" + (anchor.present? ? "##{anchor}" : '') - when :anchor; - "##{page.present? ? Wiki.titleize(page) : title}" + (anchor.present? ? "_#{anchor}" : '') # used for single-file wiki export - else - wiki_page_id = page.present? ? Wiki.titleize(page) : nil - parent = wiki_page.nil? && obj.is_a?(WikiContent) && obj.page && project == link_project ? obj.page.title : nil - url_for(:only_path => only_path, :controller => 'wiki', :action => 'show', :project_id => link_project, - :id => wiki_page_id, :version => nil, :anchor => anchor, :parent => parent) - end - end - link_to(title.present? ? title.html_safe : h(page), url, :class => ('wiki-page' + (wiki_page ? '' : ' new'))) - else - # project or wiki doesn't exist - all - end - else - all - end - end - end - - def select_option_helper option - tmp = Hash.new - tmp={"" => ""} - option.each do |project| - tmp[project.name] = project.id - end - tmp - end - - # Redmine links - # - # Examples: - # Issues: - # #52 -> Link to issue #52 - # Changesets: - # r52 -> Link to revision 52 - # commit:a85130f -> Link to scmid starting with a85130f - # Documents: - # document#17 -> Link to document with id 17 - # document:Greetings -> Link to the document with title "Greetings" - # document:"Some document" -> Link to the document with title "Some document" - # Versions: - # version#3 -> Link to version with id 3 - # version:1.0.0 -> Link to version named "1.0.0" - # version:"1.0 beta 2" -> Link to version named "1.0 beta 2" - # Source files: - # source:some/file -> Link to the file located at /some/file in the project's repository - # source:some/file@52 -> Link to the file's revision 52 - # source:some/file#L120 -> Link to line 120 of the file - # source:some/file@52#L120 -> Link to line 120 of the file's revision 52 - # export:some/file -> Force the download of the file - # Forum messages: - # message#1218 -> Link to message with id 1218 - # - # Links can refer other objects from other projects, using project identifier: - # identifier:r52 - # identifier:document:"Some document" - # identifier:version:1.0.0 - # identifier:source:some/file - - HEADING_RE = /(\{\{([<>]?)toc\}\}<\/p>/i unless const_defined?(:TOC_RE) - - # Renders the TOC with given headings - def replace_toc(text, headings) - text.gsub!(TOC_RE) do - # Keep only the 4 first levels - headings = headings.select { |level, anchor, item| level <= 4 } - if headings.empty? - '' - else - div_class = 'toc' - div_class << ' right' if $1 == '>' - div_class << ' left' if $1 == '<' - out = "
- "
- root = headings.map(&:first).min
- current = root
- started = false
- headings.each do |level, anchor, item|
- if level > current
- out << '
- ' * (level - current) - elsif level < current - out << "
- " - elsif started - out << '
- ' - end - out << "#{item}" - current = level - started = true - end - out << '
").# 2+ newline -> 2 br - gsub(/([^\n]\n)(?=[^\n])/, '\1
').# 1 newline -> br - html_safe - end - - def lang_options_for_select(blank=true) - {'Chinese简体中文 ' => 'zh', :English => :en} - end - - def label_tag_for(name, option_tags = nil, options = {}) - label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required") : "") - content_tag("label", label_text) - end - - def labelled_form_for(*args, &proc) - args << {} unless args.last.is_a?(Hash) - options = args.last - if args.first.is_a?(Symbol) - options.merge!(:as => args.shift) - end - options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) - form_for(*args, &proc) - end - - def labelled_fields_for(*args, &proc) - args << {} unless args.last.is_a?(Hash) - options = args.last - options.merge!({:builder => Redmine::Views::LabelledFormBuilder}) - fields_for(*args, &proc) - end - - def labelled_remote_form_for(*args, &proc) - ActiveSupport::Deprecation.warn "ApplicationHelper#labelled_remote_form_for is deprecated and will be removed in Redmine 2.2." - args << {} unless args.last.is_a?(Hash) - options = args.last - options.merge!({:builder => Redmine::Views::LabelledFormBuilder, :remote => true}) - form_for(*args, &proc) - end - - def error_messages_for(*objects) - html = "" - # modified by fq - if objects.first.is_a?(Array) - objects = objects.first - end - # end - objects = objects.map { |o| o.is_a?(String) ? instance_variable_get("@#{o}") : o }.compact - errors = objects.map { |o| o.errors.full_messages }.flatten - if errors.any? - html << "
- \n"
- errors.each do |error|
- ###by xianbo
- if (error!=l(:label_repository_path_not_null))
- html << "
- #{h error} \n" - end - ###xianbo - end - ###by xianbo - unless params[:repository].nil? - if params[:repository][:upassword]=="" - html << "
- "+ l(:label_password_not_null) +" \n" - end - end - ###xianbo - html << "
- '
- tree.keys.sort.each do |file|
- style = 'change'
- text = File.basename(h(file))
- if s = tree[file][:s]
- style << ' folder'
- path_param = to_path_param(@repository.relative_path(file))
- text = link_to(h(text), :controller => 'repositories',
- :action => 'show',
- :id => @project,
- :repository_id => @repository.identifier_param,
- :path => path_param,
- :rev => @changeset.identifier)
- output << "
- #{text}" - output << render_changes_tree(s) - output << " " - elsif c = tree[file][:c] - style << " change-#{c.action}" - path_param = to_path_param(@repository.relative_path(c.path)) - text = link_to(h(text), :controller => 'repositories', - :action => 'entry', - :id => @project, - :repository_id => @repository.identifier_param, - :path => path_param, - :rev => @changeset.identifier) unless c.action == 'D' - text << " - #{h(c.revision)}" unless c.revision.blank? - text << ' ('.html_safe + link_to(l(:label_diff), :controller => 'repositories', - :action => 'diff', - :id => @project, - :repository_id => @repository.identifier_param, - :path => path_param, - :rev => @changeset.identifier) + ') '.html_safe if c.action == 'M' - text << ' '.html_safe + content_tag('span', h(c.from_path), :class => 'copied-from') unless c.from_path.blank? - output << "
- #{text} " - end - end - output << '
'.html_safe + - "".html_safe+"#{l(:label_exist_repository_path)}"+"".html_safe) + - content_tag('p', form.text_field(:login, :size => 30))+ - content_tag('p', form.password_field( - :password, :size => 30, :name => 'ignore', - :value => ((repository.new_record? || repository.password.blank?) ? '' : ('x'*15)), - :onfocus => "this.value=''; this.name='repository[password]';", - :onchange => "this.name='repository[password]';")) - end - # by xianbo - def subversion_field_tags_new(form, repository) - - end - # def darcs_field_tags(form, repository) - # content_tag('p', form.text_field( - # :url, :label => l(:field_path_to_repository), - # :size => 60, :required => true, - # :disabled => !repository.safe_attribute?('url'))) + - # content_tag('p', form.select( - # :log_encoding, [nil] + Setting::ENCODINGS, - # :label => l(:field_commit_logs_encoding), :required => true)) - # end - - # def mercurial_field_tags(form, repository) - # content_tag('p', form.text_field( - # :url, :label => l(:field_path_to_repository), - # :size => 60, :required => true, - # :disabled => !repository.safe_attribute?('url') - # ) + - # '
'.html_safe + l(:text_mercurial_repository_note)) + - # content_tag('p', form.select( - # :path_encoding, [nil] + Setting::ENCODINGS, - # :label => l(:field_scm_path_encoding) - # ) + - # '
'.html_safe + l(:text_scm_path_encoding_note)) - # end - - def git_field_tags(form, repository) - # content_tag('p', form.text_field( - # :url, :label => l(:field_path_to_repository), - # :size => 60, :required => true, - # :disabled => !repository.safe_attribute?('url') - # ) + - # '
'.html_safe + - # l(:text_git_repository_note)) + - content_tag('p', form.select( - :path_encoding, [nil] + Setting::ENCODINGS, - :label => l(:field_scm_path_encoding) - ) + - '
'.html_safe + l(:text_scm_path_encoding_note)) + - content_tag('p', form.check_box( - :extra_report_last_commit, - :label => l(:label_git_report_last_commit) - )) - end -# by xianbo - def git_field_tags_new(form, repository) - content_tag('p', form.check_box( - :extra_report_last_commit, - :label => l(:label_git_report_last_commit) - )) - end - # def cvs_field_tags(form, repository) - # content_tag('p', form.text_field( - # :root_url, - # :label => l(:field_cvsroot), - # :size => 60, :required => true, - # :disabled => !repository.safe_attribute?('root_url'))) + - # content_tag('p', form.text_field( - # :url, - # :label => l(:field_cvs_module), - # :size => 30, :required => true, - # :disabled => !repository.safe_attribute?('url'))) + - # content_tag('p', form.select( - # :log_encoding, [nil] + Setting::ENCODINGS, - # :label => l(:field_commit_logs_encoding), :required => true)) + - # content_tag('p', form.select( - # :path_encoding, [nil] + Setting::ENCODINGS, - # :label => l(:field_scm_path_encoding) - # ) + - # '
'.html_safe + l(:text_scm_path_encoding_note)) - # end - - # def bazaar_field_tags(form, repository) - # content_tag('p', form.text_field( - # :url, :label => l(:field_path_to_repository), - # :size => 60, :required => true, - # :disabled => !repository.safe_attribute?('url'))) + - # content_tag('p', form.select( - # :log_encoding, [nil] + Setting::ENCODINGS, - # :label => l(:field_commit_logs_encoding), :required => true)) - # end - - def filesystem_field_tags(form, repository) - content_tag('p', form.text_field( - :url, :label => l(:field_root_directory), - :size => 60, :required => true, - :disabled => !repository.safe_attribute?('url'))) + - content_tag('p', form.select( - :path_encoding, [nil] + Setting::ENCODINGS, - :label => l(:field_scm_path_encoding) - ) + - '
'.html_safe + l(:text_scm_path_encoding_note)) - end - - def index_commits(commits, heads) - return nil if commits.nil? or commits.first.parents.nil? - refs_map = {} - heads.each do |head| - refs_map[head.scmid] ||= [] - refs_map[head.scmid] << head - end - commits_by_scmid = {} - commits.reverse.each_with_index do |commit, commit_index| - commits_by_scmid[commit.scmid] = { - :parent_scmids => commit.parents.collect { |parent| parent.scmid }, - :rdmid => commit_index, - :refs => refs_map.include?(commit.scmid) ? refs_map[commit.scmid].join(" ") : nil, - :scmid => commit.scmid, - :href => block_given? ? yield(commit.scmid) : commit.scmid - } - end - heads.sort! { |head1, head2| head1.to_s <=> head2.to_s } - space = nil - heads.each do |head| - if commits_by_scmid.include? head.scmid - space = index_head((space || -1) + 1, head, commits_by_scmid) - end - end - # when no head matched anything use first commit - space ||= index_head(0, commits.first, commits_by_scmid) - return commits_by_scmid, space - end - - def index_head(space, commit, commits_by_scmid) - stack = [[space, commits_by_scmid[commit.scmid]]] - max_space = space - until stack.empty? - space, commit = stack.pop - commit[:space] = space if commit[:space].nil? - space -= 1 - commit[:parent_scmids].each_with_index do |parent_scmid, parent_index| - parent_commit = commits_by_scmid[parent_scmid] - if parent_commit and parent_commit[:space].nil? - stack.unshift [space += 1, parent_commit] - end - end - max_space = space if max_space < space - end - max_space - end -end - - diff --git a/trustie2/app/helpers/roles_helper.rb b/trustie2/app/helpers/roles_helper.rb deleted file mode 100644 index 44fea58d6..000000000 --- a/trustie2/app/helpers/roles_helper.rb +++ /dev/null @@ -1,21 +0,0 @@ -# encoding: utf-8 -# -# Redmine - project management software -# Copyright (C) 2006-2013 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 RolesHelper -end diff --git a/trustie2/app/helpers/routes_helper.rb b/trustie2/app/helpers/routes_helper.rb deleted file mode 100644 index 3fc71d655..000000000 --- a/trustie2/app/helpers/routes_helper.rb +++ /dev/null @@ -1,39 +0,0 @@ -# encoding: utf-8 -# -# Redmine - project management software -# Copyright (C) 2006-2013 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 RoutesHelper - - # Returns the path to project issues or to the cross-project - # issue list if project is nil - def _project_issues_path(project, *args) - if project - project_issues_path(project, *args) - else - issues_path(*args) - end - end - - def _project_calendar_path(project, *args) - project ? project_calendar_path(project, *args) : issues_calendar_path(*args) - end - - # def _project_gantt_path(project, *args) - # project ? project_gantt_path(project, *args) : issues_gantt_path(*args) - # end -end diff --git a/trustie2/app/helpers/school_helper.rb b/trustie2/app/helpers/school_helper.rb deleted file mode 100644 index 0528cb7ac..000000000 --- a/trustie2/app/helpers/school_helper.rb +++ /dev/null @@ -1,2 +0,0 @@ -module SchoolHelper -end diff --git a/trustie2/app/helpers/search_helper.rb b/trustie2/app/helpers/search_helper.rb deleted file mode 100644 index e44c5f8a9..000000000 --- a/trustie2/app/helpers/search_helper.rb +++ /dev/null @@ -1,70 +0,0 @@ -# encoding: utf-8 -# -# Redmine - project management software -# Copyright (C) 2006-2013 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 SearchHelper - def highlight_tokens(text, tokens) - return text unless text && tokens && !tokens.empty? - re_tokens = tokens.collect {|t| Regexp.escape(t)} - regexp = Regexp.new "(#{re_tokens.join('|')})", Regexp::IGNORECASE - result = '' - text.split(regexp).each_with_index do |words, i| - if result.length > 1200 - # maximum length of the preview reached - result << '...' - break - end - words = words.mb_chars - if i.even? - result << h(words.length > 100 ? "#{words.slice(0..44)} ... #{words.slice(-45..-1)}" : words) - else - t = (tokens.index(words.downcase) || 0) % 4 - result << content_tag('span', h(words), :class => "highlight token-#{t}") - end - end - result.html_safe - end - - def type_label(t) - l("label_#{t.singularize}_plural", :default => t.to_s.humanize) - end - - def project_select_tag - options = [[l(:label_project_all), 'all']] - options << [l(:label_my_projects), 'my_projects'] unless User.current.memberships.empty? - options << [l(:label_and_its_subprojects, @project.name), 'subprojects'] unless @project.nil? || @project.descendants.active.empty? - options << [@project.name, ''] unless @project.nil? - label_tag("scope", l(:description_project_scope), :class => "hidden-for-sighted") + - select_tag('scope', options_for_select(options, params[:scope].to_s)) if options.size > 1 - end - - def render_results_by_type(results_by_type) - links = [] - # Sorts types by results count - results_by_type.keys.sort {|a, b| results_by_type[b] <=> results_by_type[a]}.each do |t| - c = results_by_type[t] - next if c == 0 - text = "#{type_label(t)} (#{c})" - links << link_to(h(text), :q => params[:q], :titles_only => params[:titles_only], - :all_words => params[:all_words], :scope => params[:scope], t => 1) - end - ('
- '.html_safe +
- links.map {|link| content_tag('li', link)}.join(' ').html_safe +
- '
| - | <%= text_field_tag 'username', params[:username], :tabindex => '1' %> | -
| - | <%= password_field_tag 'password', nil, :tabindex => '2' %> | -
| - | <%= text_field_tag "openid_url", nil, :tabindex => '3' %> | -
| - | - <% if Setting.autologin? %> - - <% end %> - | -
| - - <% if Setting.lost_password? %> - <%= link_to l(:label_password_lost), lost_password_path %> - <% end %> - - - - - | -|
<%= submit_tag l(:label_logout) %>
-<% end %> diff --git a/trustie2/app/views/account/lost_password.html.erb b/trustie2/app/views/account/lost_password.html.erb deleted file mode 100644 index ceb387e03..000000000 --- a/trustie2/app/views/account/lost_password.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<%=l(:label_password_lost)%>
- -<%= form_tag(lost_password_path) do %> -- - <%= text_field_tag 'mail', nil, :size => 40 %> - <%= submit_tag l(:button_submit) %> -
-<%=l(:label_password_lost)%>
- -<%= error_messages_for 'user' %> - -<%= form_tag(lost_password_path) do %> - <%= hidden_field_tag 'token', @token.value %> -- - <%= password_field_tag 'new_password', nil, :size => 25 %> - <%= l(:text_caracters_minimum, :count => Setting.password_min_length) %> -
- -- - <%= password_field_tag 'new_password_confirmation', nil, :size => 25 %> -
-<%= submit_tag l(:button_save) %>
-<% end %> diff --git a/trustie2/app/views/account/register.html.erb b/trustie2/app/views/account/register.html.erb deleted file mode 100644 index f24f7d052..000000000 --- a/trustie2/app/views/account/register.html.erb +++ /dev/null @@ -1,403 +0,0 @@ - - - - - - - -<%=l(:label_register)%> <%=link_to l(:label_login_with_open_id_option), signin_url if Setting.openid? %>
- -<%= labelled_form_for @user, :url => register_path do |f| %> -<%= error_messages_for 'user' %> - -| <%= l(:label_identity) %> * | -- | -- - - -<% else %> -<%= text_field_tag :no, nil, :placeholder => "请输入学号" %> - -<% end %> - - |
<%= f.text_field :login, :size => 25, :required => true %> - <%= l(:label_max_number) %>
-<%= f.password_field :password, :size => 25, :required => true %> - <%= l(:text_caracters_minimum, :count => Setting.password_min_length) %>
- -<%= f.password_field :password_confirmation, :size => 25, :required => true %>
-<% end %> - - -<%= f.text_field :mail, :required => true %>
-- <%="#{l(:label_mail_attention)} "%>
-<%= f.select :language, lang_options_for_select , :required => true %>
- - - - - - -| <%= l(:label_location) %> * | -- | -- |
| <%= submit_tag l(:button_submit) %> |
<%= f.text_field :identity_url %>
-<% end %> - - -<% @user.custom_field_values.select {|v| v.editable? || v.required?}.each do |value| %> -<%= custom_field_tag_with_label :user, value %>
-<% end %> - - - - - \ No newline at end of file diff --git a/trustie2/app/views/activities/index.html.erb b/trustie2/app/views/activities/index.html.erb deleted file mode 100644 index 907d21ee2..000000000 --- a/trustie2/app/views/activities/index.html.erb +++ /dev/null @@ -1,85 +0,0 @@ -<%= @author.nil? ? l(:label_activity) : l(:label_user_activity, link_to_user(@author)).html_safe %>
-- <%= l(:label_date_from_to, :start => format_date(@date_to - @days), :end => format_date(@date_to-1)) %> -
- - -
|
- ||||||||
-
- <%= pagination_links_full @activity_pages%>
-
<%= l(:label_activity) %>
-
- <% @activity.event_types.each do |t| %>
- <%= check_box_tag "show_#{t}", 1, @activity.scope.include?(t) %>
-
-
- <% end %>
-
- -
-<% end %> -<%= hidden_field_tag('user_id', params[:user_id]) unless params[:user_id].blank? %> -- <%= submit_tag l(:button_apply), :class => 'button-small', :name => nil %> -
-<% end %> -<% end %> - -<% html_title(l(:label_activity), @author) -%> diff --git a/trustie2/app/views/admin/_menu.html.erb b/trustie2/app/views/admin/_menu.html.erb deleted file mode 100644 index 59202a844..000000000 --- a/trustie2/app/views/admin/_menu.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%= l(:field_language) %>: - <%= select_tag 'lang', options_for_select(lang_options_for_select(false), current_language.to_s) %> - <%= submit_tag l(:text_load_default_configuration) %>
-<% end %> -<%=l(:label_administration)%>
- - <%= render :partial => 'menu' %> -<%=l(:label_information_plural)%>
- -<%= Redmine::Info.versioned_name %>
- -| <%= l(label) %> | -<%= image_tag((result ? 'true.png' : 'exclamation.png'), - :style => "vertical-align:bottom;") %> | -
-
<%= Redmine::Info.environment %>-
<%= l(:label_plugins) %>
- -<% if @plugins.any? %> -| <%=h plugin.name %> - <%= content_tag('span', h(plugin.description), :class => 'description') unless plugin.description.blank? %> - <%= content_tag('span', link_to(h(plugin.url), plugin.url), :class => 'url') unless plugin.url.blank? %> - | -<%= plugin.author_url.blank? ? h(plugin.author) : link_to(h(plugin.author), plugin.author_url) %> | -<%=h plugin.version %> | -<%= link_to(l(:button_configure), plugin_settings_path(plugin)) if plugin.configurable? %> | -
<%= l(:label_no_data) %>
-<% end %> diff --git a/trustie2/app/views/admin/projects.html.erb b/trustie2/app/views/admin/projects.html.erb deleted file mode 100644 index 2f520a236..000000000 --- a/trustie2/app/views/admin/projects.html.erb +++ /dev/null @@ -1,45 +0,0 @@ -<%=l(:label_project_plural)%>
- -<%= form_tag({}, :method => :get) do %> - -<% end %> - - -| <%=l(:label_project)%> | -<%=l(:field_is_public)%> | -<%=l(:field_created_on)%> | -- |
|---|---|---|---|
| <%= link_to_project_settings(project, {}, :title => project.short_description) %> | -<%= checked_image project.is_public? %> | -<%= format_date(project.created_on) %> | -- <%= link_to(l(:button_archive), { :controller => 'projects', :action => 'archive', :id => project, :status => params[:status] }, :data => {:confirm => l(:text_are_you_sure)}, :method => :post, :class => 'icon icon-lock') unless project.archived? %> - <%= link_to(l(:button_unarchive), { :controller => 'projects', :action => 'unarchive', :id => project, :status => params[:status] }, :method => :post, :class => 'icon icon-unlock') if project.archived? && (project.parent.nil? || !project.parent.archived?) %> - <%= link_to(l(:button_copy), { :controller => 'projects', :action => 'copy', :id => project }, :class => 'icon icon-copy') %> - <%= link_to(l(:button_delete), project_path(project), :method => :delete, :class => 'icon icon-del') %> - | -
<%= l(:label_user_plural)%>
- - <%= form_tag(:controller => 'users', :action => 'search', :method => :get) do %> - - <% end %> - - -| - | |||||||
|---|---|---|---|---|---|---|---|
| <%= avatar(user, :size => "14") %><%= link_to h(user.login), edit_user_path(user) %> | -<%= h(user.firstname) %> | -<%= h(user.lastname) %> | -<%= mail_to(h(user.mail)) %> | -<%= checked_image user.admin? %> | -<%= format_time(user.created_on) %> | -<%= format_time(user.last_login_on) unless user.last_login_on.nil? %> | -<%= change_status_link(user) %> - <%= delete_link user_path(user, :back_url => users_path(params)) unless User.current == user %> | -
-
- <%= pagination_links_full @user_pages, @user_count %>
-
<%= pluralize(@apply_project_master.errors.count, "error") %> prohibited this apply_project_master from being saved:
- --
- <% @apply_project_master.errors.full_messages.each do |msg| %>
-
- <%= msg %> - <% end %> -
Editing apply_project_master
- -<%= render 'form' %> - -<%= link_to 'Show', @apply_project_master %> | -<%= link_to 'Back', apply_project_masters_path %> diff --git a/trustie2/app/views/apply_project_masters/index.html.erb b/trustie2/app/views/apply_project_masters/index.html.erb deleted file mode 100644 index 16023cd83..000000000 --- a/trustie2/app/views/apply_project_masters/index.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -Listing apply_project_masters
- -| - | - | - |
|---|---|---|
| <%= link_to 'Show', apply_project_master %> | -<%= link_to 'Edit', edit_apply_project_master_path(apply_project_master) %> | -<%= link_to 'Destroy', apply_project_master, method: :delete, data: { confirm: 'Are you sure?' } %> | -
- -<%= link_to 'New Apply project master', new_apply_project_master_path %> diff --git a/trustie2/app/views/apply_project_masters/new.html.erb b/trustie2/app/views/apply_project_masters/new.html.erb deleted file mode 100644 index 7cdcac28b..000000000 --- a/trustie2/app/views/apply_project_masters/new.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -
New apply_project_master
- -<%= render 'form' %> - -<%= link_to 'Back', apply_project_masters_path %> diff --git a/trustie2/app/views/apply_project_masters/show.html.erb b/trustie2/app/views/apply_project_masters/show.html.erb deleted file mode 100644 index a7edc11ff..000000000 --- a/trustie2/app/views/apply_project_masters/show.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -<%= notice %>
- - -<%= link_to 'Edit', edit_apply_project_master_path(@apply_project_master) %> | -<%= link_to 'Back', apply_project_masters_path %> diff --git a/trustie2/app/views/auth_sources/_form.html.erb b/trustie2/app/views/auth_sources/_form.html.erb deleted file mode 100644 index 05c6ca9e9..000000000 --- a/trustie2/app/views/auth_sources/_form.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -<%= error_messages_for 'auth_source' %> - -<%= f.text_field :name, :required => true %>
-<%= f.check_box :onthefly_register, :label => :field_onthefly %>
-<%= f.text_field :name, :required => true %>
-<%= f.text_field :host, :required => true %>
-<%= f.text_field :port, :required => true, :size => 6 %> <%= f.check_box :tls, :no_label => true %> LDAPS
-<%= f.text_field :account %>
-<%= f.password_field :account_password, :label => :field_password, - :name => 'dummy_password', - :value => ((@auth_source.new_record? || @auth_source.account_password.blank?) ? '' : ('x'*15)), - :onfocus => "this.value=''; this.name='auth_source[account_password]';", - :onchange => "this.name='auth_source[account_password]';" %>
-<%= f.text_field :base_dn, :required => true, :size => 60 %>
-<%= f.text_field :filter, :size => 60, :label => :field_auth_source_ldap_filter %>
-<%= f.text_field :timeout, :size => 4 %>
-<%= f.check_box :onthefly_register, :label => :field_onthefly %>
-<%=l(:label_auth_source)%> (<%= h(@auth_source.auth_method_name) %>)
- -<%= labelled_form_for @auth_source, :as => :auth_source, :url => auth_source_path(@auth_source), :html => {:id => 'auth_source_form'} do |f| %> - <%= render :partial => auth_source_partial_name(@auth_source), :locals => { :f => f } %> - <%= submit_tag l(:button_save) %> -<% end %> diff --git a/trustie2/app/views/auth_sources/index.html.erb b/trustie2/app/views/auth_sources/index.html.erb deleted file mode 100644 index e35e13c26..000000000 --- a/trustie2/app/views/auth_sources/index.html.erb +++ /dev/null @@ -1,31 +0,0 @@ -<%=l(:label_auth_source_plural)%>
- -| <%=l(:field_name)%> | -<%=l(:field_type)%> | -<%=l(:field_host)%> | -<%=l(:label_user_plural)%> | -- |
|---|---|---|---|---|
| <%= link_to(h(source.name), :action => 'edit', :id => source)%> | -<%= h source.auth_method_name %> | -<%= h source.host %> | -<%= h source.users.count %> | -- <%= link_to l(:button_test), try_connection_auth_source_path(source), :class => 'icon icon-test' %> - <%= delete_link auth_source_path(source) %> - | -
<%=l(:label_auth_source_new)%> (<%= h(@auth_source.auth_method_name) %>)
- -<%= labelled_form_for @auth_source, :as => :auth_source, :url => auth_sources_path, :html => {:id => 'auth_source_form'} do |f| %> - <%= hidden_field_tag 'type', @auth_source.type %> - <%= render :partial => auth_source_partial_name(@auth_source), :locals => { :f => f } %> - <%= submit_tag l(:button_create) %> -<% end %> diff --git a/trustie2/app/views/auto_completes/issues.html.erb b/trustie2/app/views/auto_completes/issues.html.erb deleted file mode 100644 index 45e15cb89..000000000 --- a/trustie2/app/views/auto_completes/issues.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<%= raw @issues.map {|issue| { - 'id' => issue.id, - 'label' => "#{issue.tracker} ##{issue.id}: #{truncate issue.title.to_s, :length => 60}", - 'value' => issue.id - } - }.to_json -%> diff --git a/trustie2/app/views/avatar/_avatar_form.html.erb b/trustie2/app/views/avatar/_avatar_form.html.erb deleted file mode 100644 index 2f6a9ffc2..000000000 --- a/trustie2/app/views/avatar/_avatar_form.html.erb +++ /dev/null @@ -1,61 +0,0 @@ - -<%= f.text_field :name, :required => true %>
-<%= f.text_field :description, :required => true, :size => 30 %>
-<% if @board.valid_parents.any? %> -<%= f.select :parent_id, boards_options_for_select(@board.valid_parents), :include_blank => true, :label => :field_board_parent %>
-<% end %> -<%= l(:label_board) %>
- -<%= labelled_form_for @board, :url => project_board_path(@project, @board) do |f| %> - <%= render :partial => 'form', :locals => {:f => f} %> - <%= submit_tag l(:button_save) %> -<% end %> diff --git a/trustie2/app/views/boards/index.html.erb b/trustie2/app/views/boards/index.html.erb deleted file mode 100644 index 614066613..000000000 --- a/trustie2/app/views/boards/index.html.erb +++ /dev/null @@ -1,42 +0,0 @@ -<%= l(:label_board_plural) %>
-| <%= l(:label_board) %> | -<%= l(:label_topic_plural) %> | -<%= l(:label_message_plural) %> | -<%= l(:label_message_last) %> | -
|---|---|---|---|
|
- <%= link_to h(board.name), project_board_path(board.project, board), :class => "board" %> - <%=h board.description %> - |
- <%= board.topics_count %> | - - -
<%= l(:label_board_new) %>
- -<%= labelled_form_for @board, :url => project_boards_path(@project) do |f| %> - <%= render :partial => 'form', :locals => {:f => f} %> - <%= submit_tag l(:button_create) %> -<% end %> diff --git a/trustie2/app/views/boards/show.html.erb b/trustie2/app/views/boards/show.html.erb deleted file mode 100644 index 79d4da23c..000000000 --- a/trustie2/app/views/boards/show.html.erb +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - --
| <%= link_to image_tag(url_to_avatar(topic.author), :class => "avatar"), user_path(topic.author) %> | -
-
|
- |||||||
<%= l(:label_no_data) %>
-<% end %> -<%= @query.new_record? ? l(:label_calendar) : h(@query.name) %>
- -<%= form_tag({:controller => 'calendars', :action => 'show', :project_id => @project}, - :method => :get, :id => 'query_form') do %> -<%= hidden_field_tag 'set_filter', '1' %> - - -- <%= link_to_previous_month(@year, @month) %> | <%= link_to_next_month(@year, @month) %> -
- - -<% end %> - -<%= error_messages_for 'query' %> -<% if @query.valid? %> -<%= render :partial => 'common/calendar', :locals => {:calendar => @calendar} %> - -- <%= l(:text_tip_issue_begin_day) %> - <%= l(:text_tip_issue_end_day) %> - <%= l(:text_tip_issue_begin_end_day) %> -
-<% end %> - -<% content_for :sidebar do %> - <%= render :partial => 'issues/sidebar' %> -<% end %> - -<% html_title(l(:label_calendar)) -%> diff --git a/trustie2/app/views/context_menus/issues.html.erb b/trustie2/app/views/context_menus/issues.html.erb deleted file mode 100644 index b30c3a81f..000000000 --- a/trustie2/app/views/context_menus/issues.html.erb +++ /dev/null @@ -1,139 +0,0 @@ --
- <%= call_hook(:view_issues_context_menu_start, {:issues => @issues, :can => @can, :back => @back }) %>
-
- <% if @issue -%>
-
- <%= context_menu_link l(:button_edit), edit_issue_path(@issue), - :class => 'icon-edit', :disabled => !@can[:edit] %> - <% else %> -
- <%= context_menu_link l(:button_edit), bulk_edit_issues_path(:ids => @issue_ids), - :class => 'icon-edit', :disabled => !@can[:edit] %> - <% end %> - - <% if @allowed_statuses.present? %> -
-
- <%= l(:field_status) %>
-
-
- <% @allowed_statuses.each do |s| -%>
-
- <%= context_menu_link h(s.name), bulk_update_issues_path(:ids => @issue_ids, :issue => {:status_id => s}, :back_url => @back), :method => :post, - :selected => (@issue && s == @issue.status), :disabled => !@can[:update] %> - <% end -%> -
- <% end %>
-
- <% if @trackers.present? %>
- -
- <%= l(:field_tracker) %>
-
-
- <% @trackers.each do |t| -%>
-
- <%= context_menu_link h(t.name), bulk_update_issues_path(:ids => @issue_ids, :issue => {'tracker_id' => t}, :back_url => @back), :method => :post, - :selected => (@issue && t == @issue.tracker), :disabled => !@can[:edit] %> - <% end -%> -
- <% end %>
-
- <% if @safe_attributes.include?('priority_id') && @priorities.present? -%>
- -
- <%= l(:field_priority) %>
-
-
- <% @priorities.each do |p| -%>
-
- <%= context_menu_link h(p.name), bulk_update_issues_path(:ids => @issue_ids, :issue => {'priority_id' => p}, :back_url => @back), :method => :post, - :selected => (@issue && p == @issue.priority), :disabled => (!@can[:edit] || @issues.detect {|i| !i.leaf?}) %> - <% end -%> -
- <% end %>
-
- <% if @safe_attributes.include?('fixed_version_id') && @versions.present? -%>
- -
- <%= l(:field_fixed_version) %>
-
-
- <% @versions.sort.each do |v| -%>
-
- <%= context_menu_link format_version_name(v), bulk_update_issues_path(:ids => @issue_ids, :issue => {'fixed_version_id' => v}, :back_url => @back), :method => :post, - :selected => (@issue && v == @issue.fixed_version), :disabled => !@can[:update] %> - <% end -%> -
- <%= context_menu_link l(:label_none), bulk_update_issues_path(:ids => @issue_ids, :issue => {'fixed_version_id' => 'none'}, :back_url => @back), :method => :post, - :selected => (@issue && @issue.fixed_version.nil?), :disabled => !@can[:update] %> -
- <% end %>
-
- <% if @safe_attributes.include?('assigned_to_id') && @assignables.present? -%>
- -
- <%= l(:field_assigned_to) %>
-
-
- <% if @assignables.include?(User.current) %>
-
- <%= context_menu_link "<< #{l(:label_me)} >>", bulk_update_issues_path(:ids => @issue_ids, :issue => {'assigned_to_id' => User.current}, :back_url => @back), :method => :post, - :disabled => !@can[:update] %> - <% end %> - <% @assignables.each do |u| -%> -
- <%= context_menu_link h(u.name), bulk_update_issues_path(:ids => @issue_ids, :issue => {'assigned_to_id' => u}, :back_url => @back), :method => :post, - :selected => (@issue && u == @issue.assigned_to), :disabled => !@can[:update] %> - <% end -%> -
- <%= context_menu_link l(:label_nobody), bulk_update_issues_path(:ids => @issue_ids, :issue => {'assigned_to_id' => 'none'}, :back_url => @back), :method => :post, - :selected => (@issue && @issue.assigned_to.nil?), :disabled => !@can[:update] %> -
- <% end %>
-
- <% if @safe_attributes.include?('category_id') && @project && @project.issue_categories.any? -%>
- -
- <%= l(:field_category) %>
-
-
- <% @project.issue_categories.each do |u| -%>
-
- <%= context_menu_link h(u.name), bulk_update_issues_path(:ids => @issue_ids, :issue => {'category_id' => u}, :back_url => @back), :method => :post, - :selected => (@issue && u == @issue.category), :disabled => !@can[:update] %> - <% end -%> -
- <%= context_menu_link l(:label_none), bulk_update_issues_path(:ids => @issue_ids, :issue => {'category_id' => 'none'}, :back_url => @back), :method => :post, - :selected => (@issue && @issue.category.nil?), :disabled => !@can[:update] %> -
- <% end -%>
-
- <% if @safe_attributes.include?('done_ratio') && Issue.use_field_for_done_ratio? %>
- -
- <%= l(:field_done_ratio) %>
-
-
- <% (0..10).map{|x|x*10}.each do |p| -%>
-
- <%= context_menu_link "#{p}%", bulk_update_issues_path(:ids => @issue_ids, :issue => {'done_ratio' => p}, :back_url => @back), :method => :post, - :selected => (@issue && p == @issue.done_ratio), :disabled => (!@can[:edit] || @issues.detect {|i| !i.leaf?}) %> - <% end -%> -
- <% end %>
-
- <% @options_by_custom_field.each do |field, options| %>
- -
- <%= h(field.name) %>
-
-
- <% options.each do |text, value| %>
-
- <%= bulk_update_custom_field_context_menu_link(field, text, value || text) %> - <% end %> - <% unless field.is_required? %> -
- <%= bulk_update_custom_field_context_menu_link(field, l(:label_none), '__none__') %> - <% end %> -
- <% end %>
-
-<% if User.current.logged? %>
- - <%= watcher_link(@issues, User.current) %> -<% end %> - -<% if @issue.present? %> - <% if @can[:log_time] -%> -
- <%= context_menu_link l(:button_log_time), new_issue_time_entry_path(@issue), - :class => 'icon-time-add' %> - <% end %> -
- <%= context_menu_link l(:button_copy), project_copy_issue_path(@project, @issue), - :class => 'icon-copy', :disabled => !@can[:copy] %> -<% else %> -
- <%= context_menu_link l(:button_copy), bulk_edit_issues_path(:ids => @issue_ids, :copy => '1'), - :class => 'icon-copy', :disabled => !@can[:move] %> -<% end %> -
- <%= context_menu_link l(:button_delete), issues_path(:ids => @issue_ids, :back_url => @back), - :method => :delete, :data => {:confirm => issues_destroy_confirmation_message(@issues)}, :class => 'icon-del', :disabled => !@can[:delete] %> - - <%= call_hook(:view_issues_context_menu_end, {:issues => @issues, :can => @can, :back => @back }) %> -
-
- <% if !@time_entry.nil? -%>
-
- - <%= context_menu_link l(:button_edit), {:controller => 'timelog', :action => 'edit', :id => @time_entry}, - :class => 'icon-edit', :disabled => !@can[:edit] %> - - <% else %> -
- - <%= context_menu_link l(:button_edit), {:controller => 'timelog', :action => 'bulk_edit', :ids => @time_entries.collect(&:id)}, - :class => 'icon-edit', :disabled => !@can[:edit] %> - - <% end %> - - <%= call_hook(:view_time_entries_context_menu_start, {:time_entries => @time_entries, :can => @can, :back => @back }) %> - - <% if @activities.present? -%> -
-
- <%= l(:field_activity) %>
-
-
- <% @activities.each do |u| -%>
-
- - <%= context_menu_link h(u.name), {:controller => 'timelog', :action => 'bulk_update', :ids => @time_entries.collect(&:id), :time_entry => {'activity_id' => u}, :back_url => @back}, :method => :post, - :selected => (@time_entry && u == @time_entry.activity), :disabled => !@can[:edit] %> - - <% end -%> -
- - <%= context_menu_link l(:label_none), {:controller => 'timelog', :action => 'bulk_update', :ids => @time_entries.collect(&:id), :time_entry => {'activity_id' => 'none'}, :back_url => @back}, :method => :post, - :selected => (@time_entry && @time_entry.activity.nil?), :disabled => !@can[:edit] %> - -
- <% end %>
-
- <%= call_hook(:view_time_entries_context_menu_end, {:time_entries => @time_entries, :can => @can, :back => @back }) %>
-
- - - <%= context_menu_link l(:button_delete), - {:controller => 'timelog', :action => 'destroy', :ids => @time_entries.collect(&:id), :back_url => @back}, - :method => :delete, :data => {:confirm => l(:text_time_entries_destroy_confirmation)}, :class => 'icon-del', :disabled => !@can[:delete] %> - -
<%= f.text_field :name, :required => true %>
-<%= f.select :field_format, custom_field_formats_for_select(@custom_field), {}, :disabled => !@custom_field.new_record? %>
- -<% if @custom_field.format_in? 'list', 'user', 'version' %> -- <%= f.check_box :multiple %> - <% if !@custom_field.new_record? && @custom_field.multiple %> - <%= l(:text_turning_multiple_off) %> - <% end %> -
-<% end %> - -<% unless @custom_field.format_in? 'list', 'bool', 'date', 'user', 'version' %> -
- <%= f.text_field :min_length, :size => 5, :no_label => true %> -
- <%= f.text_field :max_length, :size => 5, :no_label => true %>
(<%=l(:text_min_max_length_info)%>)
<%= f.text_field :regexp, :size => 50 %>
(<%=l(:text_regexp_info)%>)
- <%= f.text_area :possible_values, :value => @custom_field.possible_values.to_a.join("\n"), :rows => 15 %> - <%= l(:text_custom_field_possible_values_info) %> -
-<% end %> - -<% case @custom_field.field_format %> -<% when 'bool' %> -<%= f.check_box(:default_value) %>
-<% when 'text' %> -<%= f.text_area(:default_value, :rows => 8) %>
-<% when 'date' %> -<%= f.text_field(:default_value, :size => 10) %>
- <%= calendar_for('custom_field_default_value') %> -<% when 'user', 'version' %> -<% else %> -<%= f.text_field(:default_value) %>
-<% end %> - -<%= call_hook(:view_custom_fields_form_upper_box, :custom_field => @custom_field, :form => f) %> -<%= f.check_box :is_required %>
-<%= f.check_box :is_for_all %>
-<%= f.check_box :is_filter %>
-<%= f.check_box :searchable %>
- -<% when "UserCustomField" %> -<%= f.check_box :is_required %>
-<%= f.check_box :visible %>
-<%= f.check_box :editable %>
-<%= f.check_box :is_filter %>
- -<% when "ProjectCustomField" %> -<%= f.check_box :is_required %>
-<%= f.check_box :visible %>
-<%= f.check_box :searchable %>
-<%= f.check_box :is_filter %>
- -<% when "VersionCustomField" %> -<%= f.check_box :is_required %>
-<%= f.check_box :is_filter %>
- -<% when "GroupCustomField" %> -<%= f.check_box :is_required %>
-<%= f.check_box :is_filter %>
- -<% when "TimeEntryCustomField" %> -<%= f.check_box :is_required %>
-<%= f.check_box :is_filter %>
- -<% else %> -<%= f.check_box :is_required %>
- -<% end %> -<%= call_hook(:"view_custom_fields_form_#{@custom_field.type.to_s.underscore}", :custom_field => @custom_field, :form => f) %> -| <%=l(:field_name)%> | -<%=l(:field_field_format)%> | -<%=l(:field_is_required)%> | - <% if tab[:name] == 'IssueCustomField' %> -<%=l(:field_is_for_all)%> | -<%=l(:label_used_by)%> | - <% end %> -<%=l(:button_sort)%> | -- |
|---|---|---|---|---|---|---|
| <%= link_to h(custom_field.name), edit_custom_field_path(custom_field) %> | -<%= l(Redmine::CustomFieldFormat.label_for(custom_field.field_format)) %> | -<%= checked_image custom_field.is_required? %> | - <% if tab[:name] == 'IssueCustomField' %> -<%= checked_image custom_field.is_for_all? %> | -<%= l(:label_x_projects, :count => custom_field.projects.count) if custom_field.is_a? IssueCustomField and !custom_field.is_for_all? %> | - <% end %> -<%= reorder_links('custom_field', {:action => 'update', :id => custom_field}, :put) %> | -- <%= delete_link custom_field_path(custom_field) %> - | -
<%= link_to l(:label_custom_field_new), new_custom_field_path(:type => tab[:name]), :class => 'icon icon-add' %>
diff --git a/trustie2/app/views/custom_fields/edit.html.erb b/trustie2/app/views/custom_fields/edit.html.erb deleted file mode 100644 index 7f62c0375..000000000 --- a/trustie2/app/views/custom_fields/edit.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -<%= link_to l(:label_custom_field_plural), :controller => 'custom_fields', :action => 'index' %> - » <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %> - » <%=h @custom_field.name %>
- -<%= labelled_form_for :custom_field, @custom_field, :url => custom_field_path(@custom_field), :html => {:method => :put, :id => 'custom_field_form'} do |f| %> -<%= render :partial => 'form', :locals => { :f => f } %> -<%= submit_tag l(:button_save) %> -<% end %> diff --git a/trustie2/app/views/custom_fields/index.html.erb b/trustie2/app/views/custom_fields/index.html.erb deleted file mode 100644 index fd43ea82f..000000000 --- a/trustie2/app/views/custom_fields/index.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -<%=l(:label_custom_field_plural)%>
- -<%= render_tabs custom_fields_tabs %> - -<% html_title(l(:label_custom_field_plural)) -%> diff --git a/trustie2/app/views/custom_fields/new.html.erb b/trustie2/app/views/custom_fields/new.html.erb deleted file mode 100644 index a0c8ac083..000000000 --- a/trustie2/app/views/custom_fields/new.html.erb +++ /dev/null @@ -1,19 +0,0 @@ -<%= link_to l(:label_custom_field_plural), :controller => 'custom_fields', :action => 'index' %> - » <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %> - » <%= l(:label_custom_field_new) %>
- -<%= labelled_form_for :custom_field, @custom_field, :url => custom_fields_path, :html => {:id => 'custom_field_form'} do |f| %> -<%= render :partial => 'form', :locals => { :f => f } %> -<%= hidden_field_tag 'type', @custom_field.type %> -<%= submit_tag l(:button_save) %> -<% end %> - -<%= javascript_tag do %> -$('#custom_field_field_format').change(function(){ - $.ajax({ - url: '<%= new_custom_field_path(:format => 'js') %>', - type: 'get', - data: $('#custom_field_form').serialize() - }); -}); -<% end %> diff --git a/trustie2/app/views/custom_fields/new.js.erb b/trustie2/app/views/custom_fields/new.js.erb deleted file mode 100644 index d77c97f07..000000000 --- a/trustie2/app/views/custom_fields/new.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#content').html('<%= escape_javascript(render :template => 'custom_fields/new', :layout => nil, :formats => [:html]) %>') diff --git a/trustie2/app/views/enumerations/_form.html.erb b/trustie2/app/views/enumerations/_form.html.erb deleted file mode 100644 index 8ff774d9d..000000000 --- a/trustie2/app/views/enumerations/_form.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<%= error_messages_for 'enumeration' %> - -<%= f.text_field :name %>
-<%= f.check_box :active %>
-<%= f.check_box :is_default %>
- - <% @enumeration.custom_field_values.each do |value| %> -<%= custom_field_tag_with_label :enumeration, value %>
- <% end %> -<%= l(@enumeration.option_name) %>: <%=h @enumeration %>
- -<%= form_tag({}, :method => :delete) do %> -<%= l(:text_enumeration_destroy_question, @enumeration.objects_count) %>
--<%= select_tag 'reassign_to_id', (content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---") + options_from_collection_for_select(@enumerations, 'id', 'name')) %>
-<%= link_to l(@enumeration.option_name), enumerations_path %> » <%=h @enumeration %>
- -<%= labelled_form_for :enumeration, @enumeration, :url => enumeration_path(@enumeration), :html => {:method => :put} do |f| %> - <%= render :partial => 'form', :locals => {:f => f} %> - <%= submit_tag l(:button_save) %> -<% end %> diff --git a/trustie2/app/views/enumerations/index.api.rsb b/trustie2/app/views/enumerations/index.api.rsb deleted file mode 100644 index 2fc70b987..000000000 --- a/trustie2/app/views/enumerations/index.api.rsb +++ /dev/null @@ -1,9 +0,0 @@ -api.array @klass.name.underscore.pluralize do - @enumerations.each do |enumeration| - api.__send__ @klass.name.underscore do - api.id enumeration.id - api.name enumeration.name - api.is_default enumeration.is_default - end - end -end diff --git a/trustie2/app/views/enumerations/index.html.erb b/trustie2/app/views/enumerations/index.html.erb deleted file mode 100644 index fe7634bf3..000000000 --- a/trustie2/app/views/enumerations/index.html.erb +++ /dev/null @@ -1,34 +0,0 @@ -<%=l(:label_enumerations)%>
- -<% Enumeration.get_subclasses.each do |klass| %> -<%= l(klass::OptionName) %>
- -<% enumerations = klass.shared %> -<% if enumerations.any? %> -| <%= l(:field_name) %> | -<%= l(:field_is_default) %> | -<%= l(:field_active) %> | -- | - |
|---|---|---|---|---|
| <%= link_to h(enumeration), edit_enumeration_path(enumeration) %> | -<%= checked_image enumeration.is_default? %> | -<%= checked_image enumeration.active? %> | -<%= reorder_links('enumeration', {:action => 'update', :id => enumeration}, :put) %> | -- <%= delete_link enumeration_path(enumeration) %> - | -
<%= link_to l(:label_enumeration_new), new_enumeration_path(:type => klass.name) %>
-<% end %> - -<% html_title(l(:label_enumerations)) -%> diff --git a/trustie2/app/views/enumerations/new.html.erb b/trustie2/app/views/enumerations/new.html.erb deleted file mode 100644 index 216b49298..000000000 --- a/trustie2/app/views/enumerations/new.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<%= link_to l(@enumeration.option_name), enumerations_path %> » <%=l(:label_enumeration_new)%>
- -<%= labelled_form_for :enumeration, @enumeration, :url => enumerations_path do |f| %> - <%= f.hidden_field :type %> - <%= render :partial => 'form', :locals => {:f => f} %> - <%= submit_tag l(:button_create) %> -<% end %> diff --git a/trustie2/app/views/git_usage/ch_usage.html.erb b/trustie2/app/views/git_usage/ch_usage.html.erb deleted file mode 100644 index 7041864e9..000000000 --- a/trustie2/app/views/git_usage/ch_usage.html.erb +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - -| Git使用说明 | -
|---|
| 我们将使用 git 这个分布式版本控制系统来提交代码,下面就来介绍一下代码的提交方法。 | -
- |
-
| - |
Step1: -到http://code.google.com/p/msysgit下载msysgit, 我们使用的版本是Git-1.7.4-preview20110204.exe |
-
| 安装时,选择Checkout as-is, commit as-is,这样Git 就不会修改换行风格了. 其他用缺省设置即可。 | -
| - |
Step2: -到http://code.google.com/p/tortoisegit/下载TortoiseGit,我们使用的版本是Tortoisegit-1.6.5.0-32bit.msi |
-
| 安装时, 选择TortoisePLink。 | -
| 这两个软件安装完成后, 就可以开始使用了。 | -
| - |
Step3: -在目录中右键单击TortoiseGit 再选Create Branch…就可以创建分支了。 |
-
-
| - |
在桌面上点击鼠标右键,选择TortoiseGit的Settings进行设置 |
-
| Name和Email是用来设置自己的用户名和联系方式的(user.name和user.email必须填写,这些将在版本库提交时用到, |
-
接着可以定制上下文菜单: -我们在Context Menu里勾选的是 Clone、Sync和Commit -在Set Extend Menu Item里勾选的是Import Svn Ignore、Show Reflog、Browse References、Stash Apply和Submodule Sync |
-
| - |
| - |
Step1: -创建版本库(两种途径) -(a)在文件夹中按右键, 选择Git Create repository here 就可以创建库了,在出现的窗口中, 不勾选选项, 直接按OK。 -完成上述操作后,可以看到工作区中出现了隐藏目录 .git。这个隐藏的 .git目录就是git版本库(repository)。 -- (b)从远程服务器上克隆一个已存在的版本库到本地:在目录中单击右键,选择Git Clone... 然后在URL里填入要clone的文件的地址。 |
-
| - |
Step2: -添加文件和文件夹 -在文件夹中按右键, 选Git Commit -> "master"… ,接着填写Message, 勾选Whole Project 选项, 这样Commit 的时候可以将整个项目的信息全部Commit 上去, 可以实现不需要打Tag 就能Checkout 出每次Commit 的内容. -比如: -在工作区添加file1.txt,commit以后接着修改file1.txt,再创建一个文件夹dir1, 并且放置一个file2.txt 在dir1 目 |
-
| - |
Step3: -创建分支 -在目录中单击右键,选择TortoiseGit 里的create Branch…就可以创建分支了。 -勾选Switch to new branch, 就可以跳转到建立好的分支上。 -比如: -添加一个file3.txt 后, commit 修改。接着通过Switch/Checkout….可以切换回master 分支。 |
-
| - |
Step4: -看分支情况及修改log -在目录中单击右键,选择TortoiseGit 里的Show log, 可以看分支情况和修改log。 勾选All Branches 可以看到所有分支的情况. -在Message 列中, |
-
| - |
Step5: -比较版本差异 -通过按Shift , 可以选中两个版本, 接着再按鼠标右键, 选中Compare revisions, 就可以比较两个revision 了。 |
-
| - |
Step6: -合并分支 -首先切换到master 分支, 接着点击鼠标右键选择TortoiseGit 里的Merge,就可以实现将分支合并到主版本。 |
-
| - |
Step7: -其他操作 -(a) Stash -Git 提供了一个暂存修改的功能, 称为Stash。 在一些程序进行了修改, 但还不 (b) 忽略文件 -一些编辑器在修改文件后会产生bak 文件, 一般不希望这些备份文件也加入 |
-
- Tips: |
-
在碰到不熟悉的命令时,可以通过 git help命令查看git的用户手册,命令如下: |
-
$git help <command> |
-
| - |
| 如果你用的是Linux,你可以用你的本地包管理系统(native package management system)来安装。 | -
$ yum install git-core -在redhat等系统下用yum -$apt-get install git-core -在debian,ubuntu等系统下用apt-get |
-
| - |
$git config --global user.name “your_name” -$git config --global user.email “your_email” -Name和Email是用来设置自己的用户名和联系方式的(user.name和user.email必须填写,这些将在版本库提交时用到,
- |
-
-
| - |
cd file1 -$ git add file1 -$ git init -$ git commit -a -$ git remote add [name] [版本库里给的URL(去掉http)] -$ git push [name] master -输入password后即可上传。 |
-
-
| ——Trustie团队 | -
-
-
-
-
- - - - \ No newline at end of file diff --git a/trustie2/app/views/git_usage/en_usage.html.erb b/trustie2/app/views/git_usage/en_usage.html.erb deleted file mode 100644 index 2f8695043..000000000 --- a/trustie2/app/views/git_usage/en_usage.html.erb +++ /dev/null @@ -1,346 +0,0 @@ - - - - - - -
| Git User Guide | -
|---|
| We will use git which is a distributed version control and source code management system to submit our code, here is the submission method. | -
|
- |||
Step1: |
- |||
Download msysgit from http://code.google.com/p/msysgit, the version we have used is -Git-1.7.4-preview20110204.exe. |
- |||
Please tick "Checkout as-is" and "commit as-is" options during installation so git does not modify the line feed style. Other options you can use the default settings. |
-
| - |
Step2: -Download TortoiseGit from http://code.google.com/p/tortoisegit/, the version we have used is -Tortoisegit-1.6.5.0-32bit.msi. -Please tick "TortoisePLink" option during installation. -You can start using Git when you complete the installation. |
-
| - |
Step3: -You can create a branch with method that right-click the "TortoiseGit" in the directory and check the "Create Branch… " option. |
-
| - |
Right-click on the desktop and select the "Settings" in the "TortoiseGit" -User name and email are used to set your own user name and contact information( user.name and user.email must be completed because these will be used when submitting the repository, Then you can customize the "Context Menu": -Please check the "Clone","Sync" and "Commit" options in the "Context Menu", -check the "Import Svn Ignore", "Show Reflog", "Browse References", "Stash Apply" and "Submodule Sync" in the "Set Extend Menu Item". |
-
| - |
Step1: -Create a new repository by two ways, here we go -(a) You can create a repository by right-click in the folder and select "Git Create repository here". Uncheck any options in the new window, instead of it please click "OK". -After completed these operation, you can see there is a hidden directory ( .git ) in the workspace and this hidden directory is the git repository. -(b) Clone a exist version from the remote server to local: right-click in the folder and select " Git Clone.." and fill in the URL where you had clone from. |
-
| - |
Step2: -Add the new file and folder -Right-click in the folder and select Git Commit -> "master"… , then fill in the "Message" and check the " Whole Project " option so that the whole information of the project can commit. -For example: -Create a new file in the workspace named "file1.txt", commit it, and then creat a new folder in the workspace named "dir1", after that create a new file again, but this file is in the folder dir1, named "file2.txt". After that select "Git Commit", then file1 and dir1 can be joined together. |
-
| - |
Step3: -Create a new Branch -You can create a new branch by right-click in the folder and select TortoiseGit -> " create Branch… ". -You will switch to the new branch when you check "Switch to new branch" option. -For example: -Create a new file in the workspace named "file3.txt", commit it. And you can switch to the "master" by select the "Switch/Checkout..." in the "TortoiseGit". |
-
| - |
Step4: -View and modify the log -You can view the situation of the branch by right-click in the folder and select TortoiseGit -> " Show log". Even you can also modify the log in it. And you can view all the branch's situation by check the " All Branches " option. -In the "Message" colume, |
-
| - |
Step5: -Compare the version -You can select two version in the same time by press "shift", and you can compare the different between two version by right-click the " Compare revisions ". |
-
| - |
Step6: -Merge the branch -First, you should switch to the "master", then righr-click on it and select TortoiseGit -> "Merge" so that the branch can merge into the main version. |
-
| - |
Step7: -Other operations -(a) Stash -Git provides a function named Stash to temporarily store the revised programs. When you revise some programs but still do not want to commit them, you can stash these revised programs and pop them if you need them then. -(b) Ignore Files -The editor will generate some .bak files after editing. If you do not want to add these .bak files to the repository you can select the ".bak" file and check the "*.bak" in the " Add to ignore list". Then the .bak files will not be commited.
|
-
| - |
Tips: -You can read the user manual by enter " git help " command when you are confused, command as follows: |
-
| $git help <command> | -
| - |
If you are useing Linux, you can install git through native package management system. -$ yum install git-core -if you are using redhat, you should type "yum". -$apt-get install git-core -if you are using debian or ubuntu, you should type "apt-get". |
-
| - |
$git config --global user.name “your_name”M -$git config --global user.email “your_email” -User name and email are used to set your own user name and contact information( user.name and user.email must be completed because these will be used when submitting the repository,
- |
-
| - |
cd file1 -$ git add file1 -$ git init -$ git commit -a -$ git remote add [name] [The URL which we give you in our website(with out http)] -$ git push [name] master -The last step is enter your password. |
-
-
| —— By Trustie Team | -
-
-
-
-
-
-
-
- - - diff --git a/trustie2/app/views/groups/_form.html.erb b/trustie2/app/views/groups/_form.html.erb deleted file mode 100644 index 7dc224061..000000000 --- a/trustie2/app/views/groups/_form.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -<%= error_messages_for @group %> - -
<%= f.text_field :name, :required => true, :size => 60 %>
- <% @group.custom_field_values.each do |value| %> -<%= custom_field_tag_with_label :group, value %>
- <% end %> -| <%= l(:label_project) %> | -<%= l(:label_role_plural) %> | -- |
|---|---|---|
| <%= link_to_project membership.project %> | -
- <%=h membership.roles.sort.collect(&:to_s).join(', ') %>
- <%= form_for(:membership, :remote => true,
- :url => { :action => 'edit_membership', :id => @group, :membership_id => membership },
- :html => { :id => "member-#{membership.id}-roles-form", :style => 'display:none;'}) do %>
- <% roles.each do |role| %>
- <%= submit_tag l(:button_change) %> - <%= link_to_function( - l(:button_cancel), - "$('#member-#{membership.id}-roles').show(); $('#member-#{membership.id}-roles-form').hide(); return false;" - ) %> - <% end %> - |
- - <%= link_to_function( - l(:button_edit), - "$('#member-#{membership.id}-roles').hide(); $('#member-#{membership.id}-roles-form').show(); return false;", - :class => 'icon icon-edit' - ) %> - <%= delete_link({:controller => 'groups', :action => 'destroy_membership', :id => @group, :membership_id => membership}, - :remote => true, - :method => :post) %> - | -
<%= l(:label_no_data) %>
-<% end %> -| <%= l(:label_user) %> | -- |
|---|---|
| <%= link_to_user user %> | -- <%= delete_link group_user_path(@group, :user_id => user), :remote => true %> - | -
<%= l(:label_no_data) %>
-<% end %> -<%= link_to l(:label_group_plural), groups_path %> » <%= h(@group) %>
- -<%= render_tabs group_settings_tabs %> - -<% html_title(l(:label_group), @group, l(:label_administration)) -%> diff --git a/trustie2/app/views/groups/edit_membership.js.erb b/trustie2/app/views/groups/edit_membership.js.erb deleted file mode 100644 index 679c99869..000000000 --- a/trustie2/app/views/groups/edit_membership.js.erb +++ /dev/null @@ -1,6 +0,0 @@ -<% if @membership.valid? %> - $('#tab-content-memberships').html('<%= escape_javascript(render :partial => 'groups/memberships') %>'); - $('#member-<%= @membership.id %>').effect("highlight"); -<% else %> - alert('<%= raw(escape_javascript(l(:notice_failed_to_save_members, :errors => @membership.errors.full_messages.join(', ')))) %>'); -<% end %> diff --git a/trustie2/app/views/groups/index.api.rsb b/trustie2/app/views/groups/index.api.rsb deleted file mode 100644 index 6a4efeaf7..000000000 --- a/trustie2/app/views/groups/index.api.rsb +++ /dev/null @@ -1,10 +0,0 @@ -api.array :groups do - @groups.each do |group| - api.group do - api.id group.id - api.name group.lastname - - render_api_custom_values group.visible_custom_field_values, api - end - end -end diff --git a/trustie2/app/views/groups/index.html.erb b/trustie2/app/views/groups/index.html.erb deleted file mode 100644 index a93354baa..000000000 --- a/trustie2/app/views/groups/index.html.erb +++ /dev/null @@ -1,26 +0,0 @@ -<%= l(:label_group_plural) %>
- -<% if @groups.any? %> -| <%=l(:label_group)%> | -<%=l(:label_user_plural)%> | -- |
|---|---|---|
| <%= link_to h(group), edit_group_path(group) %> | -<%= group.users.size %> | -<%= delete_link group %> | -
<%= l(:label_no_data) %>
-<% end %> diff --git a/trustie2/app/views/groups/new.html.erb b/trustie2/app/views/groups/new.html.erb deleted file mode 100644 index 20ef7a2a1..000000000 --- a/trustie2/app/views/groups/new.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -<%= link_to l(:label_group_plural), groups_path %> » <%= l(:label_group_new) %>
- -<%= labelled_form_for @group do |f| %> -<%= render :partial => 'form', :locals => { :f => f } %> -- <%= f.submit l(:button_create) %> - <%= f.submit l(:button_create_and_continue), :name => 'continue' %> -
-<% end %> diff --git a/trustie2/app/views/groups/remove_user.js.erb b/trustie2/app/views/groups/remove_user.js.erb deleted file mode 100644 index 88daa8f58..000000000 --- a/trustie2/app/views/groups/remove_user.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#tab-content-users').html('<%= escape_javascript(render :partial => 'groups/users') %>'); diff --git a/trustie2/app/views/groups/show.api.rsb b/trustie2/app/views/groups/show.api.rsb deleted file mode 100644 index 626474410..000000000 --- a/trustie2/app/views/groups/show.api.rsb +++ /dev/null @@ -1,30 +0,0 @@ -api.group do - api.id @group.id - api.name @group.lastname - - render_api_custom_values @group.visible_custom_field_values, api - - api.array :users do - @group.users.each do |user| - api.user :id => user.id, :name => user.name - end - end if include_in_api_response?('users') - - api.array :memberships do - @group.memberships.each do |membership| - api.membership do - api.id membership.id - api.project :id => membership.project.id, :name => membership.project.name - api.array :roles do - membership.member_roles.each do |member_role| - if member_role.role - attrs = {:id => member_role.role.id, :name => member_role.role.name} - attrs.merge!(:inherited => true) if member_role.inherited_from.present? - api.role attrs - end - end - end - end if membership.project - end - end if include_in_api_response?('memberships') -end diff --git a/trustie2/app/views/groups/show.html.erb b/trustie2/app/views/groups/show.html.erb deleted file mode 100644 index 4b067454b..000000000 --- a/trustie2/app/views/groups/show.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<%= link_to l(:label_group_plural), groups_path %> » <%=h @group %>
- --
-<% @group.users.each do |user| %>
-
- <%=h user %> -<% end %> -
<%= f.text_field :name, :size => 30, :required => true %>
-<%= f.select :assigned_to_id, principals_options_for_select(@project.assignable_users, @category.assigned_to), :include_blank => true %>
-<%=l(:label_issue_category_new)%>
- -<%= labelled_form_for @category, :as => 'issue_category', :url => project_issue_categories_path(@project), :remote => true do |f| %> -<%= render :partial => 'issue_categories/form', :locals => { :f => f } %> - -<% end %> diff --git a/trustie2/app/views/issue_categories/create.js.erb b/trustie2/app/views/issue_categories/create.js.erb deleted file mode 100644 index c4253b98e..000000000 --- a/trustie2/app/views/issue_categories/create.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -hideModal(); -<% select = content_tag('select', content_tag('option') + options_from_collection_for_select(@project.issue_categories, 'id', 'name', @category.id), :id => 'issue_category_id', :name => 'issue[category_id]') %> -$('#issue_category_id').replaceWith('<%= escape_javascript(select) %>'); diff --git a/trustie2/app/views/issue_categories/destroy.html.erb b/trustie2/app/views/issue_categories/destroy.html.erb deleted file mode 100644 index ae14c5ec5..000000000 --- a/trustie2/app/views/issue_categories/destroy.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -<%=l(:label_issue_category)%>: <%=h @category.name %>
- -<%= form_tag(issue_category_path(@category), :method => :delete) do %> -<%= l(:text_issue_category_destroy_question, @issue_count) %>
-
-<% if @categories.size > 0 %>
-:
-<%= label_tag "reassign_to_id", l(:description_issue_category_reassign), :class => "hidden-for-sighted" %>
-<%= select_tag 'reassign_to_id', options_from_collection_for_select(@categories, 'id', 'name') %>
<%=l(:label_issue_category)%>
- -<%= labelled_form_for @category, :as => :issue_category, - :url => issue_category_path(@category), :html => {:method => :put} do |f| %> -<%= render :partial => 'issue_categories/form', :locals => { :f => f } %> -<%= submit_tag l(:button_save) %> -<% end %> diff --git a/trustie2/app/views/issue_categories/index.api.rsb b/trustie2/app/views/issue_categories/index.api.rsb deleted file mode 100644 index 685d8a560..000000000 --- a/trustie2/app/views/issue_categories/index.api.rsb +++ /dev/null @@ -1,10 +0,0 @@ -api.array :issue_categories, api_meta(:total_count => @categories.size) do - @categories.each do |category| - api.issue_category do - api.id category.id - api.project(:id => category.project_id, :name => category.project.name) unless category.project.nil? - api.name category.name - api.assigned_to(:id => category.assigned_to_id, :name => category.assigned_to.name) unless category.assigned_to.nil? - end - end -end diff --git a/trustie2/app/views/issue_categories/issue_categories_helper.rb b/trustie2/app/views/issue_categories/issue_categories_helper.rb deleted file mode 100644 index 9189025c3..000000000 --- a/trustie2/app/views/issue_categories/issue_categories_helper.rb +++ /dev/null @@ -1,21 +0,0 @@ -# encoding: utf-8 -# -# Redmine - project management software -# Copyright (C) 2006-2013 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 IssueCategoriesHelper -end diff --git a/trustie2/app/views/issue_categories/new.html.erb b/trustie2/app/views/issue_categories/new.html.erb deleted file mode 100644 index b608e8a63..000000000 --- a/trustie2/app/views/issue_categories/new.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<%=l(:label_issue_category_new)%>
- -<%= labelled_form_for @category, :as => :issue_category, - :url => project_issue_categories_path(@project) do |f| %> -<%= render :partial => 'issue_categories/form', :locals => { :f => f } %> -<%= submit_tag l(:button_create) %> -<% end %> diff --git a/trustie2/app/views/issue_categories/new.js.erb b/trustie2/app/views/issue_categories/new.js.erb deleted file mode 100644 index 0d623495e..000000000 --- a/trustie2/app/views/issue_categories/new.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render :partial => 'issue_categories/new_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/trustie2/app/views/issue_categories/show.api.rsb b/trustie2/app/views/issue_categories/show.api.rsb deleted file mode 100644 index cefa7c8b8..000000000 --- a/trustie2/app/views/issue_categories/show.api.rsb +++ /dev/null @@ -1,6 +0,0 @@ -api.issue_category do - api.id @category.id - api.project(:id => @category.project_id, :name => @category.project.name) unless @category.project.nil? - api.name @category.name - api.assigned_to(:id => @category.assigned_to_id, :name => @category.assigned_to.name) unless @category.assigned_to.nil? -end diff --git a/trustie2/app/views/issue_relations/_form.html.erb b/trustie2/app/views/issue_relations/_form.html.erb deleted file mode 100644 index 29b7f0f14..000000000 --- a/trustie2/app/views/issue_relations/_form.html.erb +++ /dev/null @@ -1,14 +0,0 @@ -<%= error_messages_for 'relation' %> - -<%= f.select :relation_type, collection_for_relation_type_select, {}, :onchange => "setPredecessorFieldsVisibility();" %> -<%= l(:label_issue) %> #<%= f.text_field :issue_to_id, :size => 10 %> - -<%= submit_tag l(:button_add) %> -<%= link_to_function l(:button_cancel), '$("#new-relation-form").hide();'%> -
- -<%= javascript_tag "observeAutocompleteField('relation_issue_to_id', '#{escape_javascript auto_complete_issues_path(:project_id => @project, :scope => (Setting.cross_project_issue_relations? ? 'all' : nil))}')" %> - -<%= javascript_tag "setPredecessorFieldsVisibility();" %> diff --git a/trustie2/app/views/issue_relations/create.js.erb b/trustie2/app/views/issue_relations/create.js.erb deleted file mode 100644 index 03ba21975..000000000 --- a/trustie2/app/views/issue_relations/create.js.erb +++ /dev/null @@ -1,6 +0,0 @@ -$('#relations').html('<%= escape_javascript(render :partial => 'issues/relations') %>'); -<% if @relation.errors.empty? %> - $('#relation_delay').val(''); - $('#relation_issue_to_id').val(''); - $('#relation_issue_to_id').focus(); -<% end %> diff --git a/trustie2/app/views/issue_relations/destroy.js.erb b/trustie2/app/views/issue_relations/destroy.js.erb deleted file mode 100644 index f5f29d31d..000000000 --- a/trustie2/app/views/issue_relations/destroy.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#relation-<%= @relation.id %>').remove(); diff --git a/trustie2/app/views/issue_relations/index.api.rsb b/trustie2/app/views/issue_relations/index.api.rsb deleted file mode 100644 index 11ff3094b..000000000 --- a/trustie2/app/views/issue_relations/index.api.rsb +++ /dev/null @@ -1,11 +0,0 @@ -api.array :relations do - @relations.each do |relation| - api.relation do - api.id relation.id - api.issue_id relation.issue_from_id - api.issue_to_id relation.issue_to_id - api.relation_type relation.relation_type - api.delay relation.delay - end - end -end diff --git a/trustie2/app/views/issue_relations/show.api.rsb b/trustie2/app/views/issue_relations/show.api.rsb deleted file mode 100644 index bffad94ab..000000000 --- a/trustie2/app/views/issue_relations/show.api.rsb +++ /dev/null @@ -1,7 +0,0 @@ -api.relation do - api.id @relation.id - api.issue_id @relation.issue_from_id - api.issue_to_id @relation.issue_to_id - api.relation_type @relation.relation_type - api.delay @relation.delay -end diff --git a/trustie2/app/views/issue_statuses/_form.html.erb b/trustie2/app/views/issue_statuses/_form.html.erb deleted file mode 100644 index 37898737c..000000000 --- a/trustie2/app/views/issue_statuses/_form.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -<%= error_messages_for 'issue_status' %> - -<%= f.text_field :name, :required => true %>
-<% if Issue.use_status_for_done_ratio? %> -<%= f.select :default_done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }), :include_blank => true, :label => :field_done_ratio %>
-<% end %> -<%= f.check_box :is_closed %>
-<%= f.check_box :is_default %>
- -<%= call_hook(:view_issue_statuses_form, :issue_status => @issue_status) %> -<%= link_to l(:label_issue_status_plural), issue_statuses_path %> » <%=h @issue_status %>
- -<%= labelled_form_for @issue_status do |f| %> - <%= render :partial => 'form', :locals => {:f => f} %> - <%= submit_tag l(:button_save) %> -<% end %> diff --git a/trustie2/app/views/issue_statuses/index.api.rsb b/trustie2/app/views/issue_statuses/index.api.rsb deleted file mode 100644 index 8a51674d9..000000000 --- a/trustie2/app/views/issue_statuses/index.api.rsb +++ /dev/null @@ -1,10 +0,0 @@ -api.array :issue_statuses do - @issue_statuses.each do |status| - api.issue_status do - api.id status.id - api.name status.name - api.is_default status.is_default - api.is_closed status.is_closed - end - end -end diff --git a/trustie2/app/views/issue_statuses/index.html.erb b/trustie2/app/views/issue_statuses/index.html.erb deleted file mode 100644 index 940e26549..000000000 --- a/trustie2/app/views/issue_statuses/index.html.erb +++ /dev/null @@ -1,39 +0,0 @@ -<%=l(:label_issue_status_plural)%>
- -| <%=l(:field_status)%> | - <% if Issue.use_status_for_done_ratio? %> -<%=l(:field_done_ratio)%> | - <% end %> -<%=l(:field_is_default)%> | -<%=l(:field_is_closed)%> | -<%=l(:button_sort)%> | -- |
|---|---|---|---|---|---|
| <%= link_to h(status.name), edit_issue_status_path(status) %> | - <% if Issue.use_status_for_done_ratio? %> -<%= h status.default_done_ratio %> | - <% end %> -<%= checked_image status.is_default? %> | -<%= checked_image status.is_closed? %> | -<%= reorder_links('issue_status', {:action => 'update', :id => status}, :put) %> | -- <%= delete_link issue_status_path(status) %> - | -
<%= link_to l(:label_issue_status_plural), issue_statuses_path %> » <%=l(:label_issue_status_new)%>
- -<%= labelled_form_for @issue_status do |f| %> - <%= render :partial => 'form', :locals => {:f => f} %> - <%= submit_tag l(:button_create) %> -<% end %> diff --git a/trustie2/app/views/layouts/_base_college_header.html.erb b/trustie2/app/views/layouts/_base_college_header.html.erb deleted file mode 100644 index da9a58045..000000000 --- a/trustie2/app/views/layouts/_base_college_header.html.erb +++ /dev/null @@ -1,14 +0,0 @@ - - - diff --git a/trustie2/app/views/layouts/_base_enterprise_header.html.erb b/trustie2/app/views/layouts/_base_enterprise_header.html.erb deleted file mode 100644 index 8939112e9..000000000 --- a/trustie2/app/views/layouts/_base_enterprise_header.html.erb +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - diff --git a/trustie2/app/views/layouts/_base_footer.html.erb b/trustie2/app/views/layouts/_base_footer.html.erb deleted file mode 100644 index 1ae371d25..000000000 --- a/trustie2/app/views/layouts/_base_footer.html.erb +++ /dev/null @@ -1,57 +0,0 @@ - - - - -没有搜索到相关的内容!
--
-
建议您 :
- - 重新设置搜索关键词 -
- 不要使用太长的关键词 -
- 不要使用特殊符号,如"^&%$#@*%"等 -
- 清除关键词之间的空格 -
<%=l(:label_administration)%>
- <%= render :partial => 'admin/menu' %> - <% end %> -<% end %> - -<%= render :file => "layouts/base_admin" %> diff --git a/trustie2/app/views/layouts/base.html.erb b/trustie2/app/views/layouts/base.html.erb deleted file mode 100644 index fb6c1d909..000000000 --- a/trustie2/app/views/layouts/base.html.erb +++ /dev/null @@ -1,45 +0,0 @@ - - - - -<%= page_header_title %> - <% if @project.description.present? %> - <%= textilizable @project.description %> - <% end %> -
-- <%= link_to(session[:project_member_num], {:controller => 'projects', :action => 'member'}, :class => 'project_infor_tag') +'个成员'+'|' %> - <%= link_to(session[:project_focus_num], {:controller => 'projects', :action => 'focus'}, :class => 'project_infor_tag') +'个关注(' %> - <%= link_to(session[:project_investor_num], {:controller => 'projects', :action =>'investor'}, :class => 'project_infor_tag') +'个投资者)'+ '|' %> - <%= link_to(session[:project_issue_num], {:controller => 'projects', :action => 'issue'}, :class => 'project_infor_tag') +'个缺陷'+'|' %> - <%= link_to(session[:project_mission_num], {:controller =>'projects', :action =>'mission'}, :class => 'project_infor_tag')+'个任务'+'|'%> - <%= link_to(session[:project_on_num], {:controller =>'projects', :action =>'on'}, :class => 'project_infor_tag')+'个提交'+'|'%> - <%= link_to(session[:project_file_num], {:controller =>'projects', :action =>'file'}, :class => 'project_infor_tag')+'个文件' %> -
-
| 软件项目托管社区 | -<%= l(:label_user_location) %> : | -- - | -
| <%= link_to request.host()+"/forums", forums_path %> | -<%=link_to l(:label_home),home_path %> > <%=link_to '公共贴吧', :controller => 'forums', :action => 'index' %> > <%=link_to @forum.name, forum_path(@forum) %> > <%=link_to @memo.title, forum_memo_path(@forum, @memo) %> |
-
| <%= l(:label_osp_community) %> | -<%= l(:label_user_location) %> : | -
-
- <%#= form_tag(:controller => 'open_source_projects', :action => "search", :method => :get) do %>
- <%#= text_field_tag 'name', params[:name], :size => 20 %>
- <%#= hidden_field_tag 'project_type', params[:project_type] %>
- <%#= submit_tag l(:label_search), :class => "enterprise", :name => nil %>
- <%# end %>
- <%= render :partial => "open_source_projects/search_bar" %>
-
- |
-
| - <%= link_to request.host(), :controller => 'open_source_projects', :action => 'welcome' %> - | -<%= link_to l(:field_homepage), home_path %> - > - <%= link_to l(:label_osp_community), :controller => 'open_source_projects', :action => 'index' %> - > - <%= link_to @open_source_project.name, open_source_project_path(@open_source_project) %> - | -
| - <%= link_to image_tag('../images/avatars/Project/0', :class => 'avatar2', :size => '40x40'), - open_source_project_path(@open_source_project) %> - <%= link_to @open_source_project.name, open_source_project_path(@open_source_project) %> - | -- <%= l(:label_base_osp_view_num) %>:  - - <%= short_num (@open_source_project.view_num_ossean.nil?) ? 0 : @open_source_project.view_num_ossean %> - - | -- <%= l(:label_base_osp_discuss_num) %>:  - - <%= short_num (@topics_count.nil?) ? 0 : @topics_count %> - - | -- <%= l(:label_create_time) %>:  - - <%= (@open_source_project.created_time).to_s[0, 10] %> - - | -- <%= l(:label_osp_source) %>:  - - <%= show_project_sources @open_source_project.url %> - - | -
| <%=t(:label_stores_index)%> | -<%= l(:label_user_location) %> : | -- - | -
| <%= link_to request.host()+"/stores" , stores_url %> | -<%=link_to l(:label_home),home_path %> > <%=link_to l(:label_stores_index),stores_url %> |
-
- - - diff --git a/trustie2/app/views/layouts/mailer.text.erb b/trustie2/app/views/layouts/mailer.text.erb deleted file mode 100644 index 4b8c0b4f5..000000000 --- a/trustie2/app/views/layouts/mailer.text.erb +++ /dev/null @@ -1,4 +0,0 @@ -<%= Setting.emails_header %> -<%= yield %> --- -<%= Setting.emails_footer %> diff --git a/trustie2/app/views/layouts/right.html.erb b/trustie2/app/views/layouts/right.html.erb deleted file mode 100644 index 206aebadb..000000000 --- a/trustie2/app/views/layouts/right.html.erb +++ /dev/null @@ -1,15 +0,0 @@ - \ No newline at end of file diff --git a/trustie2/app/views/layouts/test_generate_code_tool.html.erb b/trustie2/app/views/layouts/test_generate_code_tool.html.erb deleted file mode 100644 index ef81cc518..000000000 --- a/trustie2/app/views/layouts/test_generate_code_tool.html.erb +++ /dev/null @@ -1,75 +0,0 @@ - -<% - select_option = [] - (select_option << ['项目', 'projects']) - #(select_option << ['课程', 'courses']) if project_type == Project::ProjectType_course - #select_option << ['热帖', 'memos'] - #select_option << ['教师', 'users_teacher'], - #select_option << ['学生', 'users_student'] -%> - - - -<%###################search topics###########################%> -<%= form_tag({controller: :relative_memos, action: :search }, method: :get, :target => :_blank) do %> -
Hello from Rails!
- - \ No newline at end of file diff --git a/trustie2/app/views/members/appliedproject.js.erb b/trustie2/app/views/members/appliedproject.js.erb deleted file mode 100644 index 766d70ff5..000000000 --- a/trustie2/app/views/members/appliedproject.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#principals_for_applied_member').html('<%= escape_javascript(render_principals_for_applied_members(@project)) %>'); diff --git a/trustie2/app/views/members/autocomplete.js.erb b/trustie2/app/views/members/autocomplete.js.erb deleted file mode 100644 index ba98983d3..000000000 --- a/trustie2/app/views/members/autocomplete.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#principals_for_new_member').html('<%= escape_javascript(render_principals_for_new_members(@project)) %>'); diff --git a/trustie2/app/views/members/create.js.erb b/trustie2/app/views/members/create.js.erb deleted file mode 100644 index 3607ce448..000000000 --- a/trustie2/app/views/members/create.js.erb +++ /dev/null @@ -1,13 +0,0 @@ -$('#tab-content-members').html('<%= escape_javascript(render :partial => 'projects/settings/members') %>'); -hideOnLoad(); - -<%if !@applied_members%> - <% if @members.present? && @members.all? {|m| m.valid? } %> - <% @members.each do |member| %> - $("#member-<%= member.id %>").effect("highlight"); - <% end %> - <% else %> - <% errors = @members.collect {|m| m.errors.full_messages}.flatten.uniq.join(', ') %> - alert('<%= raw(escape_javascript(l(:notice_failed_to_save_members, :errors => errors))) %>'); - <% end %> -<% end %> diff --git a/trustie2/app/views/members/destroy.js.erb b/trustie2/app/views/members/destroy.js.erb deleted file mode 100644 index 17beff44c..000000000 --- a/trustie2/app/views/members/destroy.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#tab-content-members').html('<%= escape_javascript(render :partial => 'projects/settings/members') %>'); -hideOnLoad(); diff --git a/trustie2/app/views/members/index.api.rsb b/trustie2/app/views/members/index.api.rsb deleted file mode 100644 index dd591ea7c..000000000 --- a/trustie2/app/views/members/index.api.rsb +++ /dev/null @@ -1,18 +0,0 @@ -api.array :memberships, api_meta(:total_count => @member_count, :offset => @offset, :limit => @limit) do - @members.each do |membership| - api.membership do - api.id membership.id - api.project :id => membership.project.id, :name => membership.project.name - api.__send__ membership.principal.class.name.underscore, :id => membership.principal.id, :name => membership.principal.name - api.array :roles do - membership.member_roles.each do |member_role| - if member_role.role - attrs = {:id => member_role.role.id, :name => member_role.role.name} - attrs.merge!(:inherited => true) if member_role.inherited_from.present? - api.role attrs - end - end - end - end - end -end diff --git a/trustie2/app/views/members/show.api.rsb b/trustie2/app/views/members/show.api.rsb deleted file mode 100644 index 55def9eab..000000000 --- a/trustie2/app/views/members/show.api.rsb +++ /dev/null @@ -1,14 +0,0 @@ -api.membership do - api.id @member.id - api.project :id => @member.project.id, :name => @member.project.name - api.__send__ @member.principal.class.name.underscore, :id => @member.principal.id, :name => @member.principal.name - api.array :roles do - @member.member_roles.each do |member_role| - if member_role.role - attrs = {:id => member_role.role.id, :name => member_role.role.name} - attrs.merge!(:inherited => true) if member_role.inherited_from.present? - api.role attrs - end - end - end -end diff --git a/trustie2/app/views/members/update.js.erb b/trustie2/app/views/members/update.js.erb deleted file mode 100644 index 245828aac..000000000 --- a/trustie2/app/views/members/update.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -$('#tab-content-members').html('<%= escape_javascript(render :partial => 'projects/settings/members') %>'); -hideOnLoad(); -$("#member-<%= @member.id %>").effect("highlight"); diff --git a/trustie2/app/views/memos/_form.html.erb b/trustie2/app/views/memos/_form.html.erb deleted file mode 100644 index 39192c1b3..000000000 --- a/trustie2/app/views/memos/_form.html.erb +++ /dev/null @@ -1,13 +0,0 @@ -<%= error_messages_for 'bid' %> - -<%= l(:label_homeworks_form_new_description) %>
- -<%= f.text_field :content, :required => true, :size => 60, :style => "width:150px;" %>
-<%= hidden_field_tag 'title', ||=@memo.title %> \ No newline at end of file diff --git a/trustie2/app/views/memos/edit.html.erb b/trustie2/app/views/memos/edit.html.erb deleted file mode 100644 index d1c1e1ef0..000000000 --- a/trustie2/app/views/memos/edit.html.erb +++ /dev/null @@ -1,34 +0,0 @@ - -<% @replying ||= false %> -
<%=l(:label_memo_edit)%>
-<%= labelled_form_for(@memo, :url => forum_memo_path(@memo.forum_id, @memo)) do |f| %> - <% if @memo.errors.any? %> -<%= pluralize(@memo.errors.count, "error") %> prohibited this memo from being saved:
--
- <% @memo.errors.full_messages.each do |msg| %>
-
- <%= msg %> - <% end %> -
<%= f.text_field :title, :required => true, :size => 96 %>
-- <% unless @replying %> - <% if @memo.safe_attribute? 'sticky' %> - <%= f.check_box :sticky %> <%= label_tag 'memo_sticky', l(:label_board_sticky) %> - <% end %> - <% if @memo.safe_attribute? 'lock' %> - <%= f.check_box :lock %> <%= label_tag 'memo_locked', l(:label_board_locked) %> - <% end %> - <% end %> -
-<%= f.text_area :content, :required => true, :size => 80, id: 'editor01' %>
- -- <%= f.submit :value => l(:button_change) %> -
| 软件项目托管社区 | -<%= l(:label_user_location) %> : | -
-
-
- |
-
| <%= link_to request.host()+"/forums", forums_path %> | -<%=link_to l(:label_home),home_path %> > <%=link_to '公共贴吧', :controller => 'forums', :action => 'index' %> > <%=link_to @forum.name %> |
-
<%=l(:label_memo_new)%>
-<%=link_to @memo.author.name, user_path(@memo.author) %>
--
<%= l(:label_reply_plural) %> (<%= @replies.nil? ? 0 : @replies.size %>)
- <% pages_count = @reply_pages.offset %> - <% @replies.each do |reply| %> --
| - <%= link_to image_tag(url_to_avatar(reply.author), :class => "avatar"), user_path(reply.author) %> - | -
- <%=h sanitize(reply.content.html_safe) %>
- |
-
| <%= authoring reply.created_at, reply.author.name %> | -
-
<%=l(:label_my_account)%>
- -<%=l(:field_login)%>: <%= link_to_user(@user, :format => :username) %>
-<%=l(:field_created_on)%>: <%= format_time(@user.created_on) %>
<%= link_to(l(:button_delete_my_account), {:action => 'destroy'}, :class => 'icon icon-del') %>
-<% end %> - -<%= l(:label_feeds_access_key) %>
- --<% if @user.rss_token %> -<%= l(:label_feeds_access_key_created_on, distance_of_time_in_words(Time.now, @user.rss_token.created_on)) %> -<% else %> -<%= l(:label_missing_feeds_access_key) %> -<% end %> -(<%= link_to l(:button_reset), {:action => 'reset_rss_key'}, :method => :post %>) -
- -<% if Setting.rest_api_enabled? %> -<%= l(:label_api_access_key) %>
-<%= h(@user.api_key) %>-
-<% if @user.api_token %> -<%= l(:label_api_access_key_created_on, distance_of_time_in_words(Time.now, @user.api_token.created_on)) %> -<% else %> -<%= l(:label_missing_api_access_key) %> -<% end %> -(<%= link_to l(:button_reset), {:action => 'reset_api_key'}, :method => :post %>) -
-<% end %> diff --git a/trustie2/app/views/my/account.html.erb b/trustie2/app/views/my/account.html.erb deleted file mode 100644 index 0418697c3..000000000 --- a/trustie2/app/views/my/account.html.erb +++ /dev/null @@ -1,558 +0,0 @@ - - - - - - - -<%= l(:label_my_account) %>
-<%= error_messages_for 'user' %> -<%= error_messages_for 'se' %> - - -<% end %> -<% html_title(l(:label_my_account)) -%> - - \ No newline at end of file diff --git a/trustie2/app/views/my/blocks/_calendar.html.erb b/trustie2/app/views/my/blocks/_calendar.html.erb deleted file mode 100644 index 41ca18a10..000000000 --- a/trustie2/app/views/my/blocks/_calendar.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -<%= l(:label_calendar) %>
- -<% calendar = Redmine::Helpers::Calendar.new(Date.today, current_language, :week) - calendar.events = calendar_items(calendar.startdt, calendar.enddt) %> - -<%= render :partial => 'common/calendar', :locals => {:calendar => calendar } %> diff --git a/trustie2/app/views/my/blocks/_documents.html.erb b/trustie2/app/views/my/blocks/_documents.html.erb deleted file mode 100644 index a55094cf1..000000000 --- a/trustie2/app/views/my/blocks/_documents.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%=l(:label_document_plural)%>
- -<%= render :partial => 'documents/document', :collection => documents_items %> diff --git a/trustie2/app/views/my/blocks/_issuesassignedtome.html.erb b/trustie2/app/views/my/blocks/_issuesassignedtome.html.erb deleted file mode 100644 index 02d8c9aa6..000000000 --- a/trustie2/app/views/my/blocks/_issuesassignedtome.html.erb +++ /dev/null @@ -1,18 +0,0 @@ -<%=l(:label_assigned_to_me_issues)%> (<%= Issue.visible.open.count(:conditions => {:assigned_to_id => ([User.current.id] + User.current.group_ids)})%>)
- -<% assigned_issues = issuesassignedtome_items %> -<%= render :partial => 'issues/list_simple', :locals => { :issues => assigned_issues } %> -<% if assigned_issues.length > 0 %> -<%= link_to l(:label_issue_view_all), :controller => 'issues', - :action => 'index', - :set_filter => 1, - :assigned_to_id => 'me', - :sort => 'priority:desc,updated_on:desc' %>
-<% end %> - -<% content_for :header_tags do %> -<%= auto_discovery_link_tag(:atom, - {:controller => 'issues', :action => 'index', :set_filter => 1, - :assigned_to_id => 'me', :format => 'atom', :key => User.current.rss_key}, - {:title => l(:label_assigned_to_me_issues)}) %> -<% end %> diff --git a/trustie2/app/views/my/blocks/_issuesreportedbyme.html.erb b/trustie2/app/views/my/blocks/_issuesreportedbyme.html.erb deleted file mode 100644 index 06bbda7f8..000000000 --- a/trustie2/app/views/my/blocks/_issuesreportedbyme.html.erb +++ /dev/null @@ -1,19 +0,0 @@ -<%=l(:label_reported_issues)%> (<%= Issue.visible.count(:conditions => { :author_id => User.current.id }) %>)
- -<% reported_issues = issuesreportedbyme_items %> -<%= render :partial => 'issues/list_simple', :locals => { :issues => reported_issues } %> -<% if reported_issues.length > 0 %> -<%= link_to l(:label_issue_view_all), :controller => 'issues', - :action => 'index', - :set_filter => 1, - :status_id => '*', - :author_id => 'me', - :sort => 'updated_on:desc' %>
-<% end %> - -<% content_for :header_tags do %> -<%= auto_discovery_link_tag(:atom, - {:controller => 'issues', :action => 'index', :set_filter => 1, - :author_id => 'me', :format => 'atom', :key => User.current.rss_key}, - {:title => l(:label_reported_issues)}) %> -<% end %> diff --git a/trustie2/app/views/my/blocks/_issueswatched.html.erb b/trustie2/app/views/my/blocks/_issueswatched.html.erb deleted file mode 100644 index 510920a08..000000000 --- a/trustie2/app/views/my/blocks/_issueswatched.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<%=l(:label_watched_issues)%> (<%= Issue.visible.watched_by(user.id).count %>)
-<% watched_issues = issueswatched_items %> - -<%= render :partial => 'issues/list_simple', :locals => { :issues => watched_issues } %> -<% if watched_issues.length > 0 %> -<%= link_to l(:label_issue_view_all), :controller => 'issues', - :action => 'index', - :set_filter => 1, - :watcher_id => 'me', - :sort => 'updated_on:desc' %>
-<% end %> diff --git a/trustie2/app/views/my/blocks/_news.html.erb b/trustie2/app/views/my/blocks/_news.html.erb deleted file mode 100644 index c478e4196..000000000 --- a/trustie2/app/views/my/blocks/_news.html.erb +++ /dev/null @@ -1,3 +0,0 @@ -<%=l(:label_news_latest)%>
- -<%= render :partial => 'news/news', :collection => news_items %> diff --git a/trustie2/app/views/my/blocks/_timelog.html.erb b/trustie2/app/views/my/blocks/_timelog.html.erb deleted file mode 100644 index aecc4d91a..000000000 --- a/trustie2/app/views/my/blocks/_timelog.html.erb +++ /dev/null @@ -1,49 +0,0 @@ -<%=l(:label_spent_time)%> (<%= l(:label_last_n_days, 7) %>)
-<% -entries = timelog_items -entries_by_day = entries.group_by(&:spent_on) -%> - -<%= l(:label_total_time) %>: <%= html_hours("%.2f" % entries.sum(&:hours).to_f) %>
-| <%= l(:label_activity) %> | -<%= l(:label_project) %> | -<%= l(:field_comments) %> | -<%= l(:field_hours) %> | -- |
|---|---|---|---|---|
| <%= day == Date.today ? l(:label_today).titleize : format_date(day) %> | -- | <%= html_hours("%.2f" % entries_by_day[day].sum(&:hours).to_f) %> | -- | |
| <%=h entry.activity %> | -<%=h entry.project %> <%= h(' - ') + link_to_issue(entry.issue, :truncate => 50) if entry.issue %> | -<%=h entry.comments %> | -<%= html_hours("%.2f" % entry.hours) %> | -- <% if entry.editable_by?(@user) -%> - <%= link_to image_tag('edit.png'), {:controller => 'timelog', :action => 'edit', :id => entry}, - :title => l(:button_edit) %> - <%= link_to image_tag('delete.png'), {:controller => 'timelog', :action => 'destroy', :id => entry}, - :data => {:confirm => l(:text_are_you_sure)}, - :method => :delete, - :title => l(:button_delete) %> - <% end -%> - | -
<%=l(:label_confirmation)%>
-<%= simple_format l(:text_account_destroy_confirmation)%>
-- <%= form_tag({}) do %> - - <%= submit_tag l(:button_delete_my_account) %> | - <%= link_to l(:button_cancel), :action => 'account' %> - <% end %> -
-<%=l(:label_my_page)%>
- -<%=l(:label_my_page)%>
- -<%=l(:button_change_password)%>
- -<%= error_messages_for 'user' %> - -<%= form_tag({}, :class => "tabular") do %> --<%= password_field_tag 'password', nil, :size => 25 %>
- --<%= password_field_tag 'new_password', nil, :size => 25 %> -<%= l(:text_caracters_minimum, :count => Setting.password_min_length) %>
- --<%= password_field_tag 'new_password_confirmation', nil, :size => 25 %>
-<%= submit_tag l(:button_apply) %> -<%= pluralize(@open_source_project.errors.count, "error") %> prohibited this open_source_project from being saved:
- --
- <% @open_source_project.errors.full_messages.each do |msg| %>
-
- <%= msg %> - <% end %> -
- <%= f.text_field :String %> -
- - - - - -
- - - - -- - - - <%#= short_num ((project.view_num.nil?)?0:project.view_num)+project.view_num_ossean+project.relative_topics.sum('view_num') %> - - <%#= content_tag('span', l(:label_view_num)) %> -
- - - - -- <%#= link_to project_info.followers_num, open_source_project_path(project) %> - - <%#= (project.result.relative_memos_num.nil?)?0:project.result.relative_memos_num.to_i %> - - <%#= content_tag('span', l(:label_x_relative_topics_count, :count => 0)) %> -
- - - - -- - - <%#= short_num((project.result.view_num_ossean.nil?)?0:project.result.view_num_ossean)%> - <%#= short_num ((project.view_num.nil?)?0:project.view_num)+project.view_num_ossean+project.relative_topics.sum('view_num') %> - - <%#= content_tag('span', l(:label_view_num)) %> -
- - - - - - - - - -| <%= link_to image_tag(url_to_avatar(topic.author), :class => "avatar"), user_path(topic.author) if topic.author%> - <%= image_tag('../images/avatars/User/0', :class => "avatar") unless topic.author%> | -
-
|
- |||||||||||||||||
- <%= l(:label_no_data) %> -
- <% end %> -| <%= link_to image_tag(url_to_avatar(topic.author), :class => "avatar"), user_path(topic.author) if topic.author%> - <%= image_tag('../images/avatars/User/0', :class => "avatar") unless topic.author%> | -
-
|
- ||||||||||||||
- <%= l(:label_no_data) %> -
- <% end %> -
- <%= (type.eql? "news") ? "新闻资讯" : ((type.eql? "blog") ? "技术博客" : "技术讨论区") %>
-
- 共有 <%=memos_count%>
- 条<%= (type.eql? "news") ? "新闻资讯" : ((type.eql? "blog") ? "技术博客" : "技术讨论帖") %>
-
-
- 更多>>
-
-
-
-
-
-
- -
-
-
- <% for i in (0..memos.length-1) %>
- <% memo_id = memos[i] %>
- <% memo = memo_id.topic %>
- <% next unless memo %>
-
-
- - --- <%= link_to h(truncate(memo.title, :length => 30)), memo.url, :target => '_blank', :onclick => "return user_trace_click_knowledge_in_project_detail(this,'#{type}','#{memo.id}','#{request.session_options[:id]}',null,'#{i+1}');" %> --- 来源: <%= link_to memo.source, memo.url, :onclick => "return user_trace_click_knowledge_in_project_detail(this,'#{type}','#{memo.id}','#{request.session_options[:id]}',null,'#{i+1}');" %> - - <%= user_url_and_time memo.author, memo.url, memo.created_time %> --
- ----
-- -- - - - --
-- -<%= link_to (memo.review_num), memo.url, :target => '_blank', :onclick => "return user_trace_click_knowledge_in_project_detail(this,'#{type}','#{memo.id}','#{request.session_options[:id]}',null,'#{i+1}');" %> -- -回帖 -- --
-- -<%= link_to (memo.view_num+memo.view_num_ossean), memo.url, :target => '_blank', :onclick => "return user_trace_click_knowledge_in_project_detail(this,'#{type}','#{memo.id}','#{request.session_options[:id]}',null,'#{i+1}');" %> -- -浏览 -
-
- <% end %>
-
全球热帖 - - <%= link_to "更多>>", open_source_project_relative_memos_path(@open_source_project, :sort_field => 'created_time DESC'), :method => 'get' %> - - -
-| <%= link_to image_tag(url_to_avatar(topic.author), :class => "avatar"), user_path(topic.author) if topic.author %> - <%= image_tag('../images/avatars/User/0', :class => "avatar") unless topic.author %> | -
-
|
- |||||||||||||||
- <%= l(:label_no_data) %> -
- <% end %> -| <%= link_to image_tag(url_to_avatar(topic.author), :class => "avatar"), user_path(topic.author) if topic.author%> - <%= image_tag('../images/avatars/User/0', :class => "avatar") unless topic.author%> | -
-
|
- ||||||||||||||
- <%= l(:label_no_data) %> -
- <% end %> -Editing open_source_project
- -<%= render 'form' %> - -<%= link_to 'Show', @open_source_project %> | -<%= link_to 'Back', open_source_projects_path %> diff --git a/trustie2/app/views/open_source_projects/index.html.erb b/trustie2/app/views/open_source_projects/index.html.erb deleted file mode 100644 index 9ba4168fa..000000000 --- a/trustie2/app/views/open_source_projects/index.html.erb +++ /dev/null @@ -1,582 +0,0 @@ -| <%= l(:label_osp_community) %> | -<%= l(:label_user_location) %> : | -
-
- <%#= text_field_tag 'name', params[:name], :size => 30 %>
- <%#= submit_tag l(:label_search), :class => "enterprise", :name => nil %>
- <%= render :partial => "search_bar" %>
-
- |
-
| - <%= link_to request.host()+"/open_source_projects", :controller => 'open_source_projects', :action => 'index' %> - | -<%= link_to l(:field_homepage), home_path %> - > <%= link_to l(:label_osp_community), :controller => 'open_source_projects', :action => 'index' %> | -
| <%= l(:label_osp_community) %> | -<%= l(:label_user_location) %> : | -
-
- <%#= form_tag(:controller => 'open_source_projects', :action => "search", :method => :get) do %>
- <%#= text_field_tag 'name', params[:name], :size => 20 %>
- <%#= hidden_field_tag 'project_type', params[:project_type] %>
- <%#= submit_tag l(:label_search), :class => "enterprise", :name => nil %>
- <%# end %>
- <%= render :partial => "open_source_projects/search_bar" %>
-
- |
-
| - <%= link_to request.host()+"/index", :controller => 'open_source_projects', :action => 'index' %> - | -<%= link_to l(:field_homepage), home_path %> - > - <%= link_to l(:label_osp_community), :controller => 'open_source_projects', :action => 'index' %> - | -
<%= l(:label_safety_analysis) %>
- - -软件安全态势
<%= link_to '更多 >>', allbug_open_source_projects_path %> --
- <% @bugs.each do |bug| %>
-
- [<%= show_description_of_bug(bug) %> - ]<%= link_to bug.title, bug.url, :target => '_blank' %> - <% end %> -
-
- <% for i in (0..@open_source_projects.size-1) %>
- <% project = @open_source_projects[i] %>
-
-
- - <%= link_to project.name, open_source_project_path(project), :class => "project root leaf", :onclick => "user_trace_click_project_in_project_list(this,#{i+1},'#{request.session_options[:id]}')" %> - - <%= render :partial => 'open_source_projects/os_project', :locals => {:project => project, :i => i} %> --
- <% end %>
-
-
- <%= pagination_links_full @projects_pages, @projects_count %>
-
New open_source_project
- -<%= render 'form' %> - -<%= link_to 'Back', open_source_projects_path %> diff --git a/trustie2/app/views/open_source_projects/search.html.erb b/trustie2/app/views/open_source_projects/search.html.erb deleted file mode 100644 index 33b813ff9..000000000 --- a/trustie2/app/views/open_source_projects/search.html.erb +++ /dev/null @@ -1,383 +0,0 @@ -| <%= l(:label_osp_community) %> | -<%= l(:label_user_location) %> : | -
-
- <%#= text_field_tag 'name', params[:name], :size => 30 %>
- <%#= submit_tag l(:label_search), :class => "enterprise", :name => nil %>
- <%= render :partial => "search_bar" %>
-
- |
-
| - <%= link_to request.host()+"/open_source_projects", :controller => 'open_source_projects', :action => 'index' %> - | -<%= link_to l(:field_homepage), home_path %> - > <%= link_to l(:label_osp_community), :controller => 'open_source_projects', :action => 'index' %> | -
| <%= l(:label_osp_community) %> | -<%= l(:label_user_location) %> : | -
-
- <%#= form_tag(:controller => 'open_source_projects', :action => "search", :method => :get) do %>
- <%#= text_field_tag 'name', params[:name], :size => 20 %>
- <%#= hidden_field_tag 'project_type', params[:project_type] %>
- <%#= submit_tag l(:label_search), :class => "enterprise", :name => nil %>
- <%# end %>
- <%= render :partial => "open_source_projects/search_bar" %>
-
- |
-
| - <%= link_to request.host()+"/index", :controller => 'open_source_projects', :action => 'index' %> - | -<%= link_to l(:field_homepage), home_path %> - > - <%= link_to l(:label_osp_community), :controller => 'open_source_projects', :action => 'index' %> - | -
-
- <% for i in (0..@open_source_projects.length-1) %>
- <% project = @open_source_projects[i] %>
- <% if !project.nil? %>
-
-
- - <%= link_to project.name, open_source_project_path(project), :class => "project root leaf", :onclick => "user_trace_click_project_in_project_list_after_search(this,#{i+1},'#{request.session_options[:id]}')" %> - - <%= render :partial => 'open_source_projects/os_project_search_list', :locals => {:project => project, :i => i} %> --
- <% end %>
- <% end %>
-
-
- <%= pagination_links_full @projects_pages, @projects_count %>
-
-
- <% if @simility_osp_array!=nil %>
- <% for i in 0..@simility_osp_array.length-1 %>
-
-
-
- <%= link_to @simility_osp_array[i].name, open_source_project_path(@simility_osp_array[i]), :onclick => "return user_trace_click_similar_project(this,'#{i+1}','#{request.session_options[:id]}');" %> - - -
- <%= @simility_osp_des[i] %> -
-
- <% end %>
- <% end %>
-
-
- <% if @relation_osp_array!=nil %>
- <% for i in 0..@relation_osp_array.length-1 %>
-
-
-
- <%= link_to @relation_osp_array[i].name, open_source_project_path(@relation_osp_array[i]), :onclick => "return user_trace_click_related_project(this,'#{i+1}','#{request.session_options[:id]}');" %> -
- <%= @relation_osp_des[i] %> -
-
- <% end %>
- <% end %>
-
工作地点分析
- - - - -工作经验分析
- - - - -相关软件分析
- - - -
- <%= (@memo_type.eql? "news") ? "新闻资讯" : ((@memo_type.eql? "blog") ? "技术博客" : "技术讨论区") %>
-
- 共有 <%=@topics_count%>
- 条<%= (@memo_type.eql? "news") ? "新闻资讯" : ((@memo_type.eql? "blog") ? "技术博客" : "技术讨论帖") %>
-
-
- 按
- <% if "review_num DESC".eql?(@sort_by) %>
- 时间
- /
- 回帖 ↓
- /
- 浏览
-
- <% elsif "created_time DESC".eql?(@sort_by) %>
- 时间 ↓
- /
- 回帖
- /
- 浏览
-
- <% elsif "view_num DESC".eql?(@sort_by) %>
- 时间
- /
- 回帖
- /
- 浏览 ↓
-
- <% elsif "review_num ASC".eql?(@sort_by) %>
- 时间
- /
- 回帖 ↑
- /
- 浏览
-
- <% elsif "created_time ASC".eql?(@sort_by) %>
- 时间 ↑
- /
- 回帖
- /
- 浏览
-
- <% elsif "view_num ASC".eql?(@sort_by) %>
- 时间
- /
- 回帖
- /
- 浏览↑
-
- <% else %>
- 时间
- /
- 回帖
- /
- 浏览
- <% end %>
-
- 排序
-
-
-
-
-
-
-
--
-
- -
-
|
-
-
-
-
-
|
-
-
- <%= l(:label_no_data) %> -
- <% end %> -
- 新闻资讯
-
- 共有<%=@news_count%>
- 条新闻资讯
-
-
- 更多>>
-
-
-
-
-
-
--
-
- 技术博客
-
- 共有 <%=@blogs_count%>
- 条技术博客
-
-
- 更多>>
-
-
-
-
-
-
--
-
- 技术讨论区
-
- 共有 <%=@posts_count%>
- 条技术讨论帖
-
-
- 更多>>
-
-
-
-
-
-
--
-
OSSEAN is upgrading, It should takes about 1 hour, Please View Later 。。。
-- <%= image_tag 'upgrading.jpg', :class =>'upgrading_img', :size => '900x900' %> -
-- <% end %> -<% elsif @whichChart == '2' %> - <% for i in (0..@chart2_city.length-1) %> -
- <% end %> -<% elsif @whichChart == '3' %> -
图不存在 正在开发
-OsseanMonitors#new
-Find me in app/views/ossean_monitors/new.html.erb
diff --git a/trustie2/app/views/ossean_monitors/show.html.erb b/trustie2/app/views/ossean_monitors/show.html.erb deleted file mode 100644 index 0db119ead..000000000 --- a/trustie2/app/views/ossean_monitors/show.html.erb +++ /dev/null @@ -1,91 +0,0 @@ -OSSEAN数据监控
-| 站点 | -类别 | -本日爬取量 | -本周爬取量 | -本月爬取量 | -本日抽取量 | -本周抽取量 | -本月抽取量 | -站点数据总量 | -站点数据流动量 | -站点数据流动率 | -||||||||||||||||||||||
| <%=item.website %> | -<%=item.category %> | - <% elsif (item.day_crawler == 0 && item.week_crawler == 0) && (item.day_extractor == 0 && item.week_extractor == 0) && (item.category == 'project')%> -<%=item.website %> | -<%=item.category %> | - <% else%> -<%=item.website %> | -<%=item.category %> | - <% end%> - - - <% if (item.day_crawler == 0 && item.week_crawler == 0) && (item.category != 'project') %> -<%=item.day_crawler %> | -<%=item.week_crawler %> | -<%=item.month_crawler %> | - <% elsif (item.day_crawler == 0 && item.week_crawler == 0) && (item.category == 'project')%> -<%=item.day_crawler %> | -<%=item.week_crawler %> | -<%=item.month_crawler %> | - <% else%> -<%=item.day_crawler %> | -<%=item.week_crawler %> | -<%=item.month_crawler %> | - <% end%> - - <% if(item.day_extractor == 0 && item.week_extractor == 0) && (item.category != 'project')%> -<%=item.day_extractor %> | -<%=item.week_extractor %> | -<%=item.month_extractor %> | - <% elsif(item.day_extractor == 0 && item.week_extractor == 0) && (item.category == 'project')%> -<%=item.day_extractor %> | -<%=item.week_extractor %> | -<%=item.month_extractor %> | - <% else%> -<%=item.day_extractor %> | -<%=item.week_extractor %> | -<%=item.month_extractor %> | - <% end%> - - <% if (item.day_crawler == 0 && item.week_crawler == 0) && (item.day_extractor == 0 && item.week_extractor == 0) && (item.category != 'project')%> -<%=item.total_num %> | - <% elsif (item.day_crawler == 0 && item.week_crawler == 0) && (item.day_extractor == 0 && item.week_extractor == 0) && (item.category == 'project')%> -<%=item.total_num %> | - <% else%> -<%=item.total_num %> | - <% end%> - - - <% if(item.flow_num == '0' && item.category != 'project')%> -<%=item.flow_num%> | -<%=(item.flow_rate*1000).to_i/10%>% | - <% elsif(item.flow_num == '0' && item.category == 'project')%> -<%=item.flow_num%> | -<%=(item.flow_rate*1000).to_i/10%>% | - <% else%> -<%=item.flow_num%> | -<%=(item.flow_rate*1000).to_i/10%>% | - <% end%> -
- - - <%= (user.Views.nil?)?0:user.Views.to_i %> - - <%= content_tag('span', "View") %> -
- - - - -- - - <%= (user.Reputation.nil?)?0:user.Reputation %> - <%#= short_num ((project.view_num.nil?)?0:project.view_num)+project.view_num_ossean+project.relative_topics.sum('view_num') %> - - <%= content_tag('span', "Reputation") %> -
- - - - -- - - <% if(project.owner_id.nil? || GithubUser.find(project.owner_id).name.nil?) %> - No information - <% else %> - <%=GithubUser.find(project.owner_id).name %> - <% end %> - - <%= content_tag('span', "Creator") %> -
- - - - -- - - <%= (project.language.nil?)?"No information":project.language %> - <%#= short_num ((project.view_num.nil?)?0:project.view_num)+project.view_num_ossean+project.relative_topics.sum('view_num') %> - - <%= content_tag('span', "Language") %> -
- - -- - - <%= format("%.4f",(match_score * 10000)) %> - <%#= short_num ((project.view_num.nil?)?0:project.view_num)+project.view_num_ossean+project.relative_topics.sum('view_num') %> - - <%= content_tag('span', "Correlation") %> -
- - - - --
- <% for i in (0..@stackoverflow_users.size-1) %>
- <% user = @stackoverflow_users[i] %>
-
-
- - <%= user.DisplayName %> - - <%= render :partial => 'ossean_sta_git_matchs/os_sta_git_match', :locals => {:user => user, :i => i} %> - -- - -
- <% end %>
-
-
- <%= pagination_links_full @users_pages, @users_count %>
-
|
- <% if(@user.ProfileImageUrl.nil?) %>
- |
- - <%= "View" %>:  - - <%= short_num_eng (@user.Views.nil?) ? 0 : @user.Views %> - - | -- <%= "Reputation" %>:  - - <%= short_num_eng (@user.Reputation.nil?) ? 0 : @user.Reputation %> - - | -- <%= "Join" %>:  - - <%= (@user.CreationDate).to_s[0, 10] %> - - | -- <%= "Location" %>:  - - <%= (@user.Location.nil?)?"no location information":@user.Location %> - - | -
-
- <% for i in (0..@sta_git_matches.size-1) %>
- <% match = @sta_git_matches[i] %>
-
-
-
- - href="<%=GithubProject.find(match.prjId).url %>" class="project root leaf"><%= GithubProject.find(match.prjId).name %> - - <%= render :partial => 'ossean_sta_git_matchs/os_sta_git_match_show', :locals => {:project => GithubProject.find(match.prjId), :i => i, :match_score => match.match_score} %> - -- - -
- <% end %>
-
- <% if(@sta_git_matches.size == 0) %>
-
-
- - No recommendation information --
- <% end %>
-
-
- <%= pagination_links_full @projects_pages, @projects_count %>
-
| <%= image_tag "/images/praise_tread/praise_false.png" , weight:"22px", height:"22px",:title => l(:label_issue_praise_over) %> | -
| <%= get_praise_num(obj)%> | -
| <%= image_tag "/images/praise_tread/tread_false.png",weight:"22px", height:"22px",:title => l(:label_issue_appraise_over) %> | -
| <%= image_tag "/images/praise_tread/praise_false.png",weight:"22px", height:"22px", :title => l(:label_issue_appraise_over) %> | -
| <%= get_praise_num(obj)%> | -
| <%= image_tag "/images/praise_tread/tread_false.png",weight:"22px", height:"22px",:title => l(:label_issue_tread_over) %> | -
| <%= link_to image_tag("/images/praise_tread/praise_true.png",weight:"22px", height:"22px",:title => l(:label_issue_praise)), - :controller=>"praise_tread",:action=>"praise_plus",:remote=>true,:obj_id => obj.id,:obj_type => obj.class%> | -
| <%= get_praise_num(obj)%> | -
| <%= link_to image_tag("/images/praise_tread/tread_true.png",weight:"22px", height:"22px",:title => l(:label_issue_tread)),:controller=>"praise_tread", - :action=>"tread_plus",:remote=>true,:obj_id => obj.id,:obj_type => obj.class %> | -
|
- <%= label_tag "available_columns", l(:description_available_columns) %>
- - <%= select_tag 'available_columns', - options_for_select(query_available_inline_columns_options(query)), - :multiple => true, :size => 10, :style => "width:150px", - :ondblclick => "moveOptions(this.form.available_columns, this.form.selected_columns);" %> - |
-
- - - |
-
- <%= label_tag "selected_columns", l(:description_selected_columns) %>
- - <%= select_tag tag_name, - options_for_select(query_selected_inline_columns_options(query)), - :id => 'selected_columns', :multiple => true, :size => 10, :style => "width:150px", - :ondblclick => "moveOptions(this.form.selected_columns, this.form.available_columns);" %> - |
-
- - - |
-
|
- |
--<%= label_tag('add_filter_select', l(:label_filter_add)) %> -<%= select_tag 'add_filter_select', filters_options_for_select(query), :name => nil %> - | -
-<%= text_field 'query', 'name', :size => 80 %>
- -<% if User.current.admin? || User.current.allowed_to?(:manage_public_queries, @project) %> --<%= check_box 'query', 'is_public', - :onchange => (User.current.admin? ? nil : 'if (this.checked) {$("#query_is_for_all").removeAttr("checked"); $("#query_is_for_all").attr("disabled", true);} else {$("#query_is_for_all").removeAttr("disabled");}') %>
-<% end %> - --<%= check_box_tag 'query_is_for_all', 1, @query.project.nil?, - :disabled => (!@query.new_record? && (@query.project.nil? || (@query.is_public? && !User.current.admin?))) %>
- --<%= check_box_tag 'default_columns', 1, @query.has_default_columns?, :id => 'query_default_columns', - :onclick => 'if (this.checked) {$("#columns").hide();} else {$("#columns").show();}' %>
- --<%= select 'query', 'group_by', @query.groupable_columns.collect {|c| [c.caption, c.name.to_s]}, :include_blank => true %>
- --<%= available_block_columns_tags(@query) %>
--<% end %> -
<%= l(:label_query) %>
- -<%= form_tag(query_path(@query), :onsubmit => 'selectAllOptions("selected_columns");', :method => :put) do %> - <%= render :partial => 'form', :locals => {:query => @query} %> - <%= submit_tag l(:button_save) %> -<% end %> diff --git a/trustie2/app/views/queries/index.api.rsb b/trustie2/app/views/queries/index.api.rsb deleted file mode 100644 index 800b4964e..000000000 --- a/trustie2/app/views/queries/index.api.rsb +++ /dev/null @@ -1,10 +0,0 @@ -api.array :queries, api_meta(:total_count => @query_count, :offset => @offset, :limit => @limit) do - @queries.each do |query| - api.query do - api.id query.id - api.name query.name - api.is_public query.is_public - api.project_id query.project_id - end - end -end diff --git a/trustie2/app/views/queries/index.html.erb b/trustie2/app/views/queries/index.html.erb deleted file mode 100644 index 573a9918f..000000000 --- a/trustie2/app/views/queries/index.html.erb +++ /dev/null @@ -1,27 +0,0 @@ -<%= l(:label_query_plural) %>
- -<% if @queries.empty? %> -<%=l(:label_no_data)%>
-<% else %> -| - <%= link_to h(query.name), :controller => 'issues', :action => 'index', :project_id => @project, :query_id => query %> - | -- - <% if query.editable_by?(User.current) %> - <%= link_to l(:button_edit), edit_query_path(query), :class => 'icon icon-edit' %> - <%= delete_link query_path(query) %> - - <% end %> - | -
<%= l(:label_query_new) %>
- -<%= form_tag(@project ? project_queries_path(@project) : queries_path, :onsubmit => 'selectAllOptions("selected_columns");') do %> - <%= render :partial => 'form', :locals => {:query => @query} %> - <%= submit_tag l(:button_save) %> -<% end %> diff --git a/trustie2/app/views/relative_memos/_show_memo.html.erb b/trustie2/app/views/relative_memos/_show_memo.html.erb deleted file mode 100644 index a41a5719c..000000000 --- a/trustie2/app/views/relative_memos/_show_memo.html.erb +++ /dev/null @@ -1,147 +0,0 @@ - - - -| <%= link_to image_tag(url_to_avatar(topic.author), :class => "avat0ar"), user_path(topic.author) if topic.author %> - <%= image_tag('../images/avatars/User/0', :class => "avatar") unless topic.author %> | -
-
|
- ||||||||||||||
- <%= l(:label_no_data) %> -
- <% end %> -| <%= l(:label_osp_community) %> | -<%= l(:label_user_location) %> : | -
-
- <%#= form_tag(:controller => 'open_source_projects', :action => "search", :method => :get) do %>
- <%#= text_field_tag 'name', params[:name], :size => 20 %>
- <%#= hidden_field_tag 'project_type', params[:project_type] %>
- <%#= submit_tag l(:label_search), :class => "enterprise", :name => nil %>
- <%# end %>
- <%= render :partial => "open_source_projects/search_bar" %>
-
- |
-
| - <%= link_to request.host()+"/index", :controller => 'open_source_projects', :action => 'index' %> - | -<%= link_to l(:field_homepage), home_path %> - > - <%= link_to '热帖搜索', :controller => 'relative_memos', :action => 'search' %> - | -
-
- <% for i in (0..@topics.length-1) %>
- <% topic = @topics[i] %>
- <% if !topic.nil? %>
-
-
- - <%= link_to topic.title, topic.url, :class => "project root leaf", :onclick => "return user_trace_click_knowledge_in_knowledge_list_after_search('#{topic.id}','#{@topics_pages.page}','#{i+1}','#{request.session_options[:id]}','#{@sort_tag}');" %> - - -- ----- -
- <%#= textilizable(short_desc(topic.content,25)) %> - <%= topic.short_content %> -
--- - -- - - <%= topic.review_num %> - - <%= content_tag('span', l(:label_review_num)) %> -
- - - - <%#= topic.collection_num %> - - <%#= content_tag('span', l(:label_collection_num)) %> - --> - -- - - - - -
- - - - -- - - - - -- - -- <%= content_tag('span', "#{l(:label_create_time)}: ") %> - <%= content_tag('span', topic.created_time.to_s[0,10]) %> -- - - - - -- <%= content_tag('span', "帖子来源:") %><%= link_to topic.url, topic.url, :onclick => "return user_trace_click_knowledge_in_knowledge_list_after_search('#{topic.id}','#{@topics_pages.page}','#{i+1}','#{request.session_options[:id]}');" %> -- - - -
- <% end %>
- <% end %>
-
-
- <%= pagination_links_full @topics_pages, @topics_count %>
-
<%=link_to @topic.author.name, user_path(@topic.author) if @topic.author%>
--
<%= l(:label_reply_plural) %> (<%= @replies.nil? ? 0 : @replies.size %>)
- <% pages_count = @reply_pages.offset %> - <% @replies.each do |reply| %> -<%= pages_count += 1 %>楼 :
-| - <% if reply.author%> - <%= link_to image_tag(url_to_avatar(reply.author), :class => "avatar"), user_path(reply.author) %> - <% else %> - <%= image_tag('../images/avatars/User/0', :class => "avatar") %> - <% end %> - | -
- <%=h reply.content.html_safe %>
-
- |
-
| - <% if reply.author %> - <%= authoring reply.created_time, reply.author.name %> - <% else %> - <%= user_url_and_time reply.username, reply.userhomeurl, reply.created_time %> - <% end %> | -
-
<%= l(:label_search) %>
- -<%= text_field_tag 'q', @question, :size => 60, :id => 'search-input' %> -<%= javascript_tag "$('#search-input').focus()" %> -<%= project_select_tag %> -<%= hidden_field_tag 'all_words', '', :id => nil %> - -<%= hidden_field_tag 'titles_only', '', :id => nil %> - -
--<% @object_types.each do |t| %> - -<% end %> -
- -<%= submit_tag l(:button_submit), :name => 'submit' %>
-<% end %> -<%= l(:label_result_plural) %> (<%= @results_by_type.values.sum %>)
--
- <% @results.each do |e| %>
-
- <%= content_tag('span', h(e.project), :class => 'project') unless @project == e.project %> <%= link_to highlight_tokens(truncate(e.event_title, :length => 255), @tokens), e.event_url %> -
- <%= highlight_tokens(e.event_description, @tokens) %> - - <% end %> -
-
- <% i = 0 %>
- <% for rt in related_tags %>
- <% i += 1 %>
-
- - <%= link_to image_tag("/images/sidebar/add.png"),:action => "index", - :current_selected_tags => selected_tags,:tag => rt,:do_what => "1", - :obj_id => obj_id,:object_flag => obj_flag %> - - <%= rt %> - - <% break if i >= 10 %> - - <%= render :partial => 'sidebar_tags',:locals => {:show_flag => obj_flag,:sg => rt }%> - - <% end %> -
-
- <% for sg in selected_tags %>
-
- - <%= link_to image_tag("/images/sidebar/minus.png"),:action => "index", - :current_selected_tags => selected_tags ,:tag => sg,:do_what => "0", - :obj_id => obj_id,:object_flag => obj_flag %> - <%= sg %> - <%= render :partial => 'sidebar_tags',:locals => {:show_flag => obj_flag,:sg => sg }%> - - <% end %> -
-<% for i in (0..projects_results.length-1) %> -<% prj = projects_results[i] %> -
- <%= l(:label_tags_project_name) %><%= link_to "#{prj.name}",{:controller => "open_source_projects",:action => "show",:id => prj.id}, :onclick => "return user_trace_click_project_after_tag_search('#{request.session_options[:id]}','#{i+1}','#{prj.id}');" %>
-
- <%= l(:label_tags_project_description) %><%= prj.short_description %>
-
-<% projects_results.each do |prj| %> -
- <%= l(:label_tags_project_name) %><%= link_to "#{prj.name}",{:controller => "projects",:action => "show",:id => prj.id}, :onclick => "return user_trace_click_project_after_tag_search('#{request.session_options[:id]}','#{i+1}','#{prj.id}');" %>
-
- <%= l(:label_tags_project_description) %><%= prj.description %>
-
- <% @topics_results.each do |topic| %> - <% if !topic.nil? %> -
- <%= topic.content.truncate(150) %> -
-- - <%= topic.review_num %> - - <%= content_tag('span', l(:label_review_num), :class => 'info-desc' ) %> -
- - -- - <%= topic.view_num+topic.view_num_ossean %> - - <%= content_tag('span', l(:label_view_num), :class => 'info-desc') %> -
-- <% users_results.each do |user| %> -
- <%= l(:label_tags_user_name) %><%= link_to ("#{user.firstname+user.lastname}"),
- :controller => "users",:action => "show",:id => user.id%>
-
- <%= l(:label_tags_user_mail) %><%= mail_to(h(user.mail)) %>
-
-
- <% unless show_flag.nil? %>
- <% case %>
- <% when show_flag == '1' %>
- <%= l(:label_user) %>(<%= @results_count %>)
- <%= render :partial => "show_users", :locals => {:users_results => users_results} %>
- <% when show_flag == '2' %>
- <%= l(:label_project) %>(<%= @results_count %>)
- <%= render :partial => "show_projects", :locals => {:projects_results => projects_results} %>
- <% when show_flag == '3' %>
- <%= l(:label_issue) %>(<%= @results_count %>)
- <%= render :partial => "show_issues", :locals => {:issues_results => issues_results} %>
- <% when show_flag == '4' %>
- <%= l(:label_requirement) %>(<%= @results_count %>)
- <%= render :partial => "show_bids", :locals => {:bids_results => bids_results} %>
- <% when show_flag == '5' %>
- <%= l(:label_forum) %>(<%= @results_count %>)
- <%= render :partial => "show_forums", :locals => {:forums_results => forums_results} %>
- <% when show_flag == '6' %>
- <% when show_flag == '7' %>
- <%= l(:label_contest_innovate) %>(<%= @results_count %>)
- <%= render :partial => "show_contests", :locals => {:contests_results => contests_results} %>
- <% when show_flag == '8' %>
- 开源项目:(<%= @results_count %>)
- <%= render :partial => "show_open_source_projects", :locals => {:projects_results => open_source_projects_results} %>
- <% when show_flag == '9' %>
- 热帖:(<%= @results_count %>)
- <%= render :partial => "show_topics", :locals => {:topics_results => topics_results} %>
- <% else %>
- <%= l(:label_tags_all_objects) %>
-
- <%= render :partial => "show_issues", :locals => {:issues_results => issues_results} %>
- <%= render :partial => "show_users", :locals => {:users_results => users_results} %>
- <%= render :partial => "show_projects", :locals => {:projects_results => projects_results} %>
- <%= render :partial => "show_bids", :locals => {:bids_results => bids_results} %>
- <%= render :partial => "show_contests", :locals => {:contests_results => contests_results} %>
- <% end %>
-
- <% else %>
- no data...
- <% end %>
-
<%= l(:label_tags_selected) %>
- - -<%= l(:label_tags_related) %>
- -总标签数:<%= @tags.size %>个
--<% i = 0 %> - diff --git a/trustie2/app/views/users/_course_form.html.erb b/trustie2/app/views/users/_course_form.html.erb deleted file mode 100644 index 13ab819dc..000000000 --- a/trustie2/app/views/users/_course_form.html.erb +++ /dev/null @@ -1,59 +0,0 @@ -
-
- <% for membership in memberships %>
-
-
-
-
-- -<%= image_tag(url_to_avatar(membership.project), :class => 'avatar') %> -- --
-- -- <%= link_to_project(membership.project) %> - - <%= render :partial => 'courses/set_course_time', :locals => {:project => membership.project} %> - <% if User.current == @user %> - <% (membership.roles).each do |role| %> - <% unless (role == Role.find(9) || role == Role.find(3)) %> - <%= join_in_course(membership.project, User.current) %> - <% end %> - <% end %> - <% else %> - <% end %> - <%= l(:label_x_base_courses_member, :count => membership.project.members.count) %> - (<%= "#{membership.project.members.count}" %>) - <%= l(:label_homework) %> - (<%= link_to (membership.project.homeworks.count), {:controller => 'projects', :action => 'homework', :id => membership.project.identifier} %>) - - <%= l(:label_course_news) %> - (<%= link_to (membership.project.news.count), {:controller => 'news', :action => 'index', :project_id => membership.project.identifier} %>) - -- -- -- <%= membership.project.description %> -
- -- - <% @course = Course.find_by_extra(membership.project.identifier) %> - <% unless (@course.nil? || @course.teacher.nil? || @course.teacher.name.nil?) %> - <%= l(:label_main_teacher) %> - : <%= link_to(@course.teacher.realname, user_path(@course.teacher)) %> - <%= l(:label_course_term) %> - : <%= @course.time %><%= @course.term %> - <% end %> - -
-
- <% end %>
-
<%= f.text_field :login, :required => true, :size => 25 %>
-<%= f.text_field :firstname, :required => true %>
-<%= f.text_field :lastname, :required => true %>
-<%= f.text_field :mail, :required => true %>
-<%= f.select :language, lang_options_for_select %>
- <% if Setting.openid? %> -<%= f.text_field :identity_url %>
- <% end %> - - <% @user.custom_field_values.each do |value| %> -<%= custom_field_tag_with_label :user, value %>
- <% end %> - -<%= f.check_box :admin, :disabled => (@user == User.current) %>
- <%= call_hook(:view_users_form, :user => @user, :form => f) %> -<%= f.select :auth_source_id, ([[l(:label_internal), ""]] + @auth_sources.collect { |a| [a.name, a.id] }), {}, :onchange => "if (this.value=='') {$('#password_fields').show();} else {$('#password_fields').hide();}" %>
- <% end %> - -<%= submit_tag l(:button_save) %>
-<% end %> diff --git a/trustie2/app/views/users/_groups.html.erb b/trustie2/app/views/users/_groups.html.erb deleted file mode 100644 index e24296ef0..000000000 --- a/trustie2/app/views/users/_groups.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -<%= form_for(:user, :url => { :action => 'update' }, :html => {:method => :put}) do %> --<% end %> -<%= hidden_field_tag 'user[group_ids][]', '' %> -
<%= l(:permission_add_issue_watchers) %>
- -<%= form_tag({:controller => 'users', - :action => (user ? 'create' : 'append'), - :object_type => (user && user.class.name.underscore), - :object_id => user, - :project_id => @project}, - :remote => true, - :method => :post, - :id => 'new-watcher-form') do %> - -<%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %>
- <%= javascript_tag "observeSearchfield('user_search', 'users_for_watcher', '#{ escape_javascript url_for(:controller => 'watchers', - :action => 'autocomplete_for_user', - :object_type => (watched && watched.class.name.underscore), - :object_id => watched, - :project_id => @project) }')" %> - --<%= label_tag "user_mail_notification", l(:description_user_mail_notification), :class => "hidden-for-sighted_bak" %> -<%= select_tag( - 'user[mail_notification]', - options_for_select( - user_mail_notification_options(@user), @user.mail_notification), - :onchange => 'if (this.value == "selected") {$("#notified-projects").show();} else {$("#notified-projects").hide();}' - ) %> -
-<%= content_tag 'div', :id => 'notified-projects', :style => (@user.mail_notification == 'selected' ? '' : 'display:none;') do %> - <%= render_project_nested_lists_new(@user.projects) do |project| - content_tag('label', - check_box_tag( - 'notified_project_ids[]', - project.id, - @user.notified_projects_ids.include?(project.id) - ) + ' ' + h(project.name) - ) - end %> -<%= l(:text_user_mail_option) %>
-<% end %> -- -
diff --git a/trustie2/app/views/users/_memberships.html.erb b/trustie2/app/views/users/_memberships.html.erb deleted file mode 100644 index 5f61d2ce2..000000000 --- a/trustie2/app/views/users/_memberships.html.erb +++ /dev/null @@ -1,67 +0,0 @@ -<% roles = Role.find_all_givable %> -<% projects = Project.active.all %> - -| <%= l(:label_project) %> | -<%= l(:label_role_plural) %> | -- <%= call_hook(:view_users_memberships_table_header, :user => @user )%> - |
|---|---|---|
| - <%= link_to_project membership.project %> - | -
- <%=h membership.roles.sort.collect(&:to_s).join(', ') %>
- <%= form_for(:membership, :remote => true,
- :url => user_membership_path(@user, membership), :method => :put,
- :html => {:id => "member-#{membership.id}-roles-form",
- :style => 'display:none;'}) do %>
- <% roles.each do |role| %>
- <%= submit_tag l(:button_change) %> - <%= link_to_function l(:button_cancel), - "$('#member-#{membership.id}-roles').show(); $('#member-#{membership.id}-roles-form').hide(); return false;" - %> - <% end %> - |
- - <%= link_to_function l(:button_edit), - "$('#member-#{membership.id}-roles').hide(); $('#member-#{membership.id}-roles-form').show(); return false;", - :class => 'icon icon-edit' - %> - <%= delete_link user_membership_path(@user, membership), :remote => true if membership.deletable? %> - | - <%= call_hook(:view_users_memberships_table_row, :user => @user, :membership => membership, :roles => roles, :projects => projects )%> -
<%= l(:label_no_data) %>
-<% end %> -<%= l(:label_role_plural) %>: -<% roles.each do |role| %> - -<% end %>
-<%= submit_tag l(:button_add) %>
-<% end %> -- <%= l(:label_project_course_un) %> -
- <% else %> -- - <%= l(:label_project_course_unadd) %><%= link_to "#{l(:label_course_new)}", {:controller => 'projects', :action => 'new', :course => 1, :project_type => 1}, :class => 'icon icon-add' %> -
- <% end %> - <% else %> - <%= render partial: 'course_list_have_entity' %> - <% end %> -| <%= link_to(image_tag(url_to_avatar(bid.author), :class => 'avatar'), user_path(bid.author), :class => "avatar") %> | -
-
|
-|||||||||
- <%= l(:label_my_create_honework_no_homework) %> -
-<% end %> \ No newline at end of file diff --git a/trustie2/app/views/users/_my_homework.html.erb b/trustie2/app/views/users/_my_homework.html.erb deleted file mode 100644 index d551e0d9f..000000000 --- a/trustie2/app/views/users/_my_homework.html.erb +++ /dev/null @@ -1,54 +0,0 @@ - -<% if @bid.size > 0%> - -<% @bid.each do |bids|%> - -<% for bid in bids[1]%> -<% unless @user == bid.author %> -| <%= link_to(image_tag(url_to_avatar(bid.author), :class => 'avatar'), user_path(bid.author), :class => "avatar") %> | -
-
|
- |||||||||
- <%= l(:label_my_honework_no_homework) %> -
-<% end %> \ No newline at end of file diff --git a/trustie2/app/views/users/_my_joinedcourse.html.erb b/trustie2/app/views/users/_my_joinedcourse.html.erb deleted file mode 100644 index 31780e301..000000000 --- a/trustie2/app/views/users/_my_joinedcourse.html.erb +++ /dev/null @@ -1,38 +0,0 @@ -- <%= l(:label_project_course_un) %> -
- <% else %> -- - <%= l(:label_project_cousre_studentun) %><%= link_to"#{l(:label_course_join_student)}",{:controller=>'projects',:action=>'course', :course => 1}, :class => 'icon icon-add' %> -
- <% end %> -<% else %> -<%= pref_fields.check_box :hide_mail %>
-<%= pref_fields.time_zone_select :time_zone, nil, :include_blank => true %>
-<%= pref_fields.select :comments_sorting, [[l(:label_chronological_order), 'asc'], [l(:label_reverse_chronological_order), 'desc']] %>
- -<% end %> diff --git a/trustie2/app/views/users/_topic_score_index.html.erb b/trustie2/app/views/users/_topic_score_index.html.erb deleted file mode 100644 index db05e9234..000000000 --- a/trustie2/app/views/users/_topic_score_index.html.erb +++ /dev/null @@ -1,23 +0,0 @@ - - - -<% messages_count = @user.messages.count %> -<% messages_score = messages_count * 0.05%> -- <%= user_extension.text_field :birthday %> -
-- <%= user_extension.select :gender, [[l(:label_boy), '1'], [l(:label_girl), '0']] %> -
- -- <%= user_extension.text_area :brief_introduction %>(少于250字) -
-- <%= user_extension.text_field :location %> -
-- <%= user_extension.text_field :occupation %> -
-- <%= user_extension.text_field :work_experience %> -
-- <%= user_extension.text_field :zip_code %> -
- -<% end %> diff --git a/trustie2/app/views/users/activity_score_index.js.erb b/trustie2/app/views/users/activity_score_index.js.erb deleted file mode 100644 index 5414d0c68..000000000 --- a/trustie2/app/views/users/activity_score_index.js.erb +++ /dev/null @@ -1,3 +0,0 @@ - -$('#show_score_detail').html('<%= escape_javascript(render :partial => 'users/activity_score_index', :locals => {:index =>0 }) %>'); - \ No newline at end of file diff --git a/trustie2/app/views/users/blocks/_calendar.html.erb b/trustie2/app/views/users/blocks/_calendar.html.erb deleted file mode 100644 index 41ca18a10..000000000 --- a/trustie2/app/views/users/blocks/_calendar.html.erb +++ /dev/null @@ -1,6 +0,0 @@ -<%= l(:label_calendar) %>
- -<% calendar = Redmine::Helpers::Calendar.new(Date.today, current_language, :week) - calendar.events = calendar_items(calendar.startdt, calendar.enddt) %> - -<%= render :partial => 'common/calendar', :locals => {:calendar => calendar } %> diff --git a/trustie2/app/views/users/blocks/_issuesassignedtome.html.erb b/trustie2/app/views/users/blocks/_issuesassignedtome.html.erb deleted file mode 100644 index 02d8c9aa6..000000000 --- a/trustie2/app/views/users/blocks/_issuesassignedtome.html.erb +++ /dev/null @@ -1,18 +0,0 @@ -<%=l(:label_assigned_to_me_issues)%> (<%= Issue.visible.open.count(:conditions => {:assigned_to_id => ([User.current.id] + User.current.group_ids)})%>)
- -<% assigned_issues = issuesassignedtome_items %> -<%= render :partial => 'issues/list_simple', :locals => { :issues => assigned_issues } %> -<% if assigned_issues.length > 0 %> -<%= link_to l(:label_issue_view_all), :controller => 'issues', - :action => 'index', - :set_filter => 1, - :assigned_to_id => 'me', - :sort => 'priority:desc,updated_on:desc' %>
-<% end %> - -<% content_for :header_tags do %> -<%= auto_discovery_link_tag(:atom, - {:controller => 'issues', :action => 'index', :set_filter => 1, - :assigned_to_id => 'me', :format => 'atom', :key => User.current.rss_key}, - {:title => l(:label_assigned_to_me_issues)}) %> -<% end %> diff --git a/trustie2/app/views/users/destroy_membership.js.erb b/trustie2/app/views/users/destroy_membership.js.erb deleted file mode 100644 index 53b769a73..000000000 --- a/trustie2/app/views/users/destroy_membership.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#tab-content-memberships').html('<%= escape_javascript(render :partial => 'users/memberships') %>'); diff --git a/trustie2/app/views/users/edit.html.erb b/trustie2/app/views/users/edit.html.erb deleted file mode 100644 index 01875ab68..000000000 --- a/trustie2/app/views/users/edit.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<%= link_to l(:label_user_plural), users_path %> » <%=h @user.login %>
- -<%= render_tabs user_settings_tabs %> - -<% html_title(l(:label_user), @user.login, l(:label_administration)) -%> diff --git a/trustie2/app/views/users/edit_membership.js.erb b/trustie2/app/views/users/edit_membership.js.erb deleted file mode 100644 index d9ad2f355..000000000 --- a/trustie2/app/views/users/edit_membership.js.erb +++ /dev/null @@ -1,6 +0,0 @@ -<% if @membership.valid? %> - $('#tab-content-memberships').html('<%= escape_javascript(render :partial => 'users/memberships') %>'); - $("#member-<%= @membership.id %>").effect("highlight"); -<% else %> - alert('<%= raw(escape_javascript(l(:notice_failed_to_save_members, :errors => @membership.errors.full_messages.join(', ')))) %>'); -<% end %> diff --git a/trustie2/app/views/users/index.api.rsb b/trustie2/app/views/users/index.api.rsb deleted file mode 100644 index 4265a4be4..000000000 --- a/trustie2/app/views/users/index.api.rsb +++ /dev/null @@ -1,15 +0,0 @@ -api.array :users, api_meta(:total_count => @user_count, :offset => @offset, :limit => @limit) do - @users.each do |user| - api.user do - api.id user.id - api.login user.login - api.firstname user.firstname - api.lastname user.lastname - api.mail user.mail - api.created_on user.created_on - api.last_login_on user.last_login_on - - render_api_custom_values user.visible_custom_field_values, api - end - end -end diff --git a/trustie2/app/views/users/index.html.erb b/trustie2/app/views/users/index.html.erb deleted file mode 100644 index 2736ec37e..000000000 --- a/trustie2/app/views/users/index.html.erb +++ /dev/null @@ -1,49 +0,0 @@ - -| <%= l(:label_software_user ) %> | -<%= l(:label_user_location) %> : | -- | -
-
- <%= text_field_tag 'name', params[:name], :size => 30 %>
- <%= submit_tag l(:label_search), :class => "enterprise", :name => nil %>
-
- |
-
| <%= link_to request.host()+"/users", :controller => 'users', :action => 'index' %> | -<%=link_to l(:field_homepage), home_path %> > <%=link_to l(:label_software_user), :controller => 'users', :action => 'index' %> | -
-
- <%= pagination_links_full @user_pages, @user_count %>
-
<%= l(:label_user_plural)%>
- -<%= form_tag(users_path, :method => :get) do %> -- Contributes to <%= user.id%> projects including -
-- 14168 total commits to 18 projects | managed 7 projects | Most experience in c++ -
--
- <%= pagination_links_full @user_pages, @user_count %>
-
-
-
<%= link_to l(:label_user_plural), users_path %> » <%=l(:label_user_new)%>
- -<%= labelled_form_for @user do |f| %> - <%= render :partial => 'form', :locals => { :f => f } %> - <% if email_delivery_enabled? %> - - <% end %> -- <%= submit_tag l(:button_create) %> - <%= submit_tag l(:button_create_and_continue), :name => 'continue' %> -
-<% end %> - -<% if @auth_sources.present? && @auth_sources.any?(&:searchable?) %> - <%= javascript_tag do %> - observeAutocompleteField('user_login', '<%= escape_javascript autocomplete_for_new_user_auth_sources_path %>', { - select: function(event, ui) { - $('input#user_firstname').val(ui.item.firstname); - $('input#user_lastname').val(ui.item.lastname); - $('input#user_mail').val(ui.item.mail); - $('select#user_auth_source_id option').each(function(){ - if ($(this).attr('value') == ui.item.auth_source_id) { - $(this).attr('selected', true); - $('select#user_auth_source_id').trigger('change'); - } - }); - } - }); - <% end %> -<% end %> diff --git a/trustie2/app/views/users/project_score_index.js.erb b/trustie2/app/views/users/project_score_index.js.erb deleted file mode 100644 index 2f23fab2a..000000000 --- a/trustie2/app/views/users/project_score_index.js.erb +++ /dev/null @@ -1,3 +0,0 @@ - -$('#show_score_detail').html('<%= escape_javascript(render :partial => 'users/project_score_index', :locals => {:index =>1 }) %>'); - \ No newline at end of file diff --git a/trustie2/app/views/users/score_index.js.erb b/trustie2/app/views/users/score_index.js.erb deleted file mode 100644 index 94e7fddd6..000000000 --- a/trustie2/app/views/users/score_index.js.erb +++ /dev/null @@ -1,3 +0,0 @@ - -$('#show_score_detail').html('<%= escape_javascript(render :partial => 'users/score_index', :locals => {:index =>0 }) %>'); - \ No newline at end of file diff --git a/trustie2/app/views/users/search.html.erb b/trustie2/app/views/users/search.html.erb deleted file mode 100644 index b2143ec6e..000000000 --- a/trustie2/app/views/users/search.html.erb +++ /dev/null @@ -1,131 +0,0 @@ -<% if User.current.admin? %> -<%= l(:label_user_plural)%>
- -<%= form_tag(:controller => 'users', :action => 'search', :method => :get) do %> -| - | |||||||
|---|---|---|---|---|---|---|---|
| <%= avatar(user, :size => "14") %><%= link_to h(user.login), edit_user_path(user) %> | -<%= h(user.firstname) %> | -<%= h(user.lastname) %> | -<%= mail_to(h(user.mail)) %> | -<%= checked_image user.admin? %> | -<%= format_time(user.created_on) %> | -<%= format_time(user.last_login_on) unless user.last_login_on.nil? %> | -<%= change_status_link(user) %> - <%= delete_link user_path(user, :back_url => users_path(params)) unless User.current == user %> | -
-
- <%= pagination_links_full @user_pages, @user_count %>
-
-
-
| <%= l(:label_software_user ) %> | -<%= l(:label_user_location) %> : | -- | -
-
- <%= text_field_tag 'name', params[:name], :size => 30 %>
- <%= submit_tag l(:label_search), :class => "enterprise", :name => nil %>
-
- |
-
| <%= link_to request.host()+"/users", :controller => 'users', :action => 'index' %> | -<%=link_to l(:field_homepage), home_path %> > <%=link_to l(:label_software_user), :controller => 'users', :action => 'index' %> | -
-
- <%= pagination_links_full @user_pages, @user_count %>
-
-
-
<%= h @user.name %>
- - -| 关注 <%= link_to User.watched_by(@user.id).count, home_path %> 粉丝 <%= link_to @user.watcher_users.count, home_path %> | -|
| <%= link_to image_tag(avatar_image(@user), :class => 'avatar'), :class => "avatar" %> | - |
| <% unless User.current == @user %> - <%= watcher_link(@user, User.current) %><% end %> | -
-
-
-
-
<%= h @user.name %>
-
- <% if @user == User.current %>
- -
-
<%= mail_to(h(@user.mail), nil, :encode => 'javascript') %>
-
- <% end %>
- -
-
<%= l(:field_last_login_on)%>: <%= format_date(@user.last_login_on) %> -
- -
- 贡献指数:
-
-
<%= link_to l(:label_user_watcher), home_path %>
--
-

-
-
<%= link_to l(:label_project_plural),home_path %>
--
- <% for membership in @memberships %>
-
-
-
-
-- - - -
- -- <%= link_to_project(membership.project) %> -- -- <%= membership.project.description%> -- -- <%= l(:label_user_watcher)%><%= link_to"999",home_path%> <%= l(:label_user_commits)%><%= link_to"12",home_path%> --- ( - <%= format_date(membership.created_on) %>) --- - -
- <% end %>
-
-
- <% for membership in @memberships %>
-
-
-
-
- - -
--
- -<%= link_to_project(membership.project) %> <%= l(:label_create_project) %> <%= link_to_project(membership.project) %> -- - -<%= membership.project.description%>
- -<%= format_date(membership.created_on) %> -<%= link_to"查看其他评论",news_path(news)%><%= "(#{l(:label_x_comments, :count => news.comments_count)})" if news.comments_count > 0 %> -
- <% end %>
-
<%= link_to l(:label_user_newfeedback), home_path %>start a... |
-
-
-
-
-
-
-- - -
- - <%= link_to "huang",home_path%>对我评价了: -- - 新建问题的时候存在一个bug,需要解决卡涵盖的垃圾卡拉格德国的萨嘎... - -
-
<%= link_to l(:label_activity), :controller => 'activities', - :action => 'index', :id => nil, :user_id => @user, - :from => @events_by_day.keys.first %>
--
- <% @events_by_day[day].sort {|x,y| y.event_datetime <=> x.event_datetime }.each do |e| -%>
-
-
-
-
-- - -
- -- <%= content_tag('span', h(e.project), :class => 'project') %> -- -- <%= link_to format_activity_title(e.event_title), e.event_url %> - <%= format_activity_description(e.event_description) %> - -
- <% end -%>
-
<%= l(:label_x_user_fans, :count => User.current.watcher_users(User.current.id).count)%>
--
-
-
- -<%= link_to image_tag(url_to_avatar(user), :class => "avatar"), - user_path(user), - :title => "#{user.name}" %> - --
- - -<%= content_tag "div", link_to(user.name,user_path(user)), :class => "project_avatar_name" %> - -- - - - - -- <% unless user.memberships.empty? %> - <% cond = Project.visible_condition(User.current) + "AND projects.project_type <> 1" %> - <% memberships = user.memberships.all(:conditions => cond) %> - <%= l(:label_x_contribute_to, :count => memberships.count) %> - <% for member in memberships %> - <%= link_to_project(member.project) %><%= (user.memberships.last == member) ? '' : ',' %> - <% end %> - <% end %> -
-- <% unless user.memberships.empty? %> - <% cond = Project.visible_condition(User.current) + "AND projects.project_type = 1" %> - <% memberships = user.memberships.all(:conditions => cond) %> - <%= l(:label_x_course_contribute_to, :count => memberships.count) %> - <% for member in memberships %> - <%= link_to_project(member.project) %><%= (user.memberships.last == member) ? '' : ',' %> - <% end %> - <% end %> -
-- -<%= l(:label_user_joinin) %><%= format_date(user.created_on) %> - -
-
- <%= pagination_links_full @feedback_pages %>
-
-
- <% for membership in @memberships %>
-
-
-
-
- -- - -<%= image_tag(url_to_avatar(membership.project), :class => 'avatar') %> -- --
- -<%= link_to_user(membership.user) if membership.respond_to?(:user) %> - <%= l(:label_peoject_take_in) %> <%= link_to_project(membership.project) %> -- -- -- <%= membership.project.description%> -
- -<%= l(:label_create_time) %> : <%= format_time(membership.created_on) %> -<%= h membership.roles.sort.collect(&:to_s).join(', ') %> -
- <% end %>
-
<%= l(:label_project_un) %>
-<% else %> -<%= l(:label_project_unadd) %>
-<% end %> - -<% end %> -<%= call_hook :view_account_left_bottom, :user => @user %> -<%= l(:label_user_watcher)%>
--
-
-
- -<%= link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :title => "#{user.name}" %> - --
- -<%= content_tag "div", link_to(user.name,user_path(user)), :class => "project_avatar_name" %> - -- - - - -- <% unless user.memberships.empty? %> - <% cond = Project.visible_condition(User.current) + "AND projects.project_type <> 1" %> - <% memberships = user.memberships.all(:conditions => cond) %> - <%= l(:label_x_contribute_to, :count => memberships.count) %> - <% for member in memberships %> - <%= link_to_project(member.project) %><%= (user.memberships.last == member) ? '' : ',' %> - <% end %> - <% end %> -
-- <% unless user.memberships.empty? %> - <% cond = Project.visible_condition(User.current) + "AND projects.project_type = 1" %> - <% memberships = user.memberships.all(:conditions => cond) %> - <%= l(:label_x_course_contribute_to, :count => memberships.count) %> - <% for member in memberships %> - <%= link_to_project(member.project) %><%= (user.memberships.last == member) ? '' : ',' %> - <% end %> - <% end %> -
-- -<%= l(:label_user_joinin) %><%= format_date(user.created_on) %> - -
| <%= image_tag(url_to_avatar(bid.author), :class => 'avatar') %> | -
-
|
- |||||||||
-
- <%= pagination_links_full @bid_pages %>
-
-
-
<%= l(:label_follow_no_requirement) %>
-<% end %> \ No newline at end of file diff --git a/trustie2/app/views/users/watch_projects.html.erb b/trustie2/app/views/users/watch_projects.html.erb deleted file mode 100644 index 42047d4ea..000000000 --- a/trustie2/app/views/users/watch_projects.html.erb +++ /dev/null @@ -1,32 +0,0 @@ -<%= link_to(l(:label_project_new), {:controller => 'projects', :action => 'new', :course => 0, :project_type => 0}, :class => 'icon icon-add') if(User.current.allowed_to?(:add_project, nil, :global => true) && @user == User.current)%> - -<%= watch_projects @state%> -<% if @watch_projects.count > 0 %> -<% for watch_project in @watch_projects %> -| <%= image_tag(url_to_avatar(watch_project.project), :class => 'avatar') %> | -
-
|
- ||||||
<%= f.text_field :name, :size => 60, :required => true %>
-<%= f.text_field :description, :size => 60, :style => "margin-left:10px;" %>
-<%= f.select :status, Version::VERSION_STATUSES.collect {|s| [l("version_status_#{s}"), s]} %>
-<%= f.text_field :wiki_page_title, :label => :label_wiki_page, :size => 60, :disabled => @project.wiki.nil? %>
-<%= f.text_field :effective_date, :size => 10 %><%= calendar_for('version_effective_date') %>
-<%= f.select :sharing, @version.allowed_sharings.collect {|v| [format_version_sharing(v), v]} %>
- -<% @version.custom_field_values.each do |value| %> -<%= custom_field_tag_with_label :version, value %>
-<% end %> - -<%= l(:label_no_data) %>
-<% else %> -| - <% if count[:group] -%> - <%= link_to(h(count[:group]), project_issues_path(version.project, :set_filter => 1, :status_id => '*', :fixed_version_id => version, "#{criteria}_id" => count[:group])) %> - <% else -%> - <%= link_to(l(:label_none), project_issues_path(version.project, :set_filter => 1, :status_id => '*', :fixed_version_id => version, "#{criteria}_id" => "!*")) %> - <% end %> - | -- <%= progress_bar((count[:closed].to_f / count[:total])*100, - :legend => "#{count[:closed]}/#{count[:total]}", - :width => "#{(count[:total].to_f / max * 200).floor}px;") %> - | -
<%=l(:label_version_new)%>
- -<%= labelled_form_for @version, :url => project_versions_path(@project), :remote => true do |f| %> -<%= render :partial => 'versions/form', :locals => { :f => f } %> - -<% end %> diff --git a/trustie2/app/views/versions/_overview.html.erb b/trustie2/app/views/versions/_overview.html.erb deleted file mode 100644 index fdb0bcd4a..000000000 --- a/trustie2/app/views/versions/_overview.html.erb +++ /dev/null @@ -1,17 +0,0 @@ - -<% if version.issues_count > 0 %> -»<%= l(:label_versions_progress)%>
- <%= progress_bar([version.closed_percent, version.completed_percent], :width => '40em', :legend => ('%0.0f%' % version.completed_percent)) %> -- <%= link_to(l(:label_x_issues, :count => version.issues_count), - project_issues_path(version.project, :status_id => '*', :fixed_version_id => version, :set_filter => 1)) %> - - (<%= link_to_if(version.closed_issues_count > 0, l(:label_x_closed_issues_abbr, :count => version.closed_issues_count), - project_issues_path(version.project, :status_id => 'c', :fixed_version_id => version, :set_filter => 1)) %> - — - <%= link_to_if(version.open_issues_count > 0, l(:label_x_open_issues_abbr, :count => version.open_issues_count), - project_issues_path(version.project, :status_id => 'o', :fixed_version_id => version, :set_filter => 1)) %>) -
-<% else %> -<%= l(:label_roadmap_no_issues) %>
-<% end %> diff --git a/trustie2/app/views/versions/create.js.erb b/trustie2/app/views/versions/create.js.erb deleted file mode 100644 index e6e0bec45..000000000 --- a/trustie2/app/views/versions/create.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -hideModal(); -<% select = content_tag('select', content_tag('option') + version_options_for_select(@project.shared_versions.open, @version), :id => 'issue_fixed_version_id', :name => 'issue[fixed_version_id]') %> -$('#issue_fixed_version_id').replaceWith('<%= escape_javascript(select) %>'); diff --git a/trustie2/app/views/versions/edit.html.erb b/trustie2/app/views/versions/edit.html.erb deleted file mode 100644 index 39db07c9d..000000000 --- a/trustie2/app/views/versions/edit.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<%=l(:label_version)%>
- -<%= labelled_form_for @version do |f| %> -<%= render :partial => 'form', :locals => { :f => f } %> -<%= submit_tag l(:button_save) %> -<% end %> - diff --git a/trustie2/app/views/versions/index.api.rsb b/trustie2/app/views/versions/index.api.rsb deleted file mode 100644 index 3adde2b98..000000000 --- a/trustie2/app/views/versions/index.api.rsb +++ /dev/null @@ -1,19 +0,0 @@ -api.array :versions, api_meta(:total_count => @versions.size) do - @versions.each do |version| - api.version do - api.id version.id - api.project(:id => version.project_id, :name => version.project.name) unless version.project.nil? - - api.name version.name - api.description version.description - api.status version.status - api.due_date version.effective_date - api.sharing version.sharing - - render_api_custom_values version.custom_field_values, api - - api.created_on version.created_on - api.updated_on version.updated_on - end - end -end diff --git a/trustie2/app/views/versions/index.html.erb b/trustie2/app/views/versions/index.html.erb deleted file mode 100644 index 184eb0f18..000000000 --- a/trustie2/app/views/versions/index.html.erb +++ /dev/null @@ -1,97 +0,0 @@ - -
- <%= link_to_function l(:label_completed_versions),
- '$("#toggle-completed-versions").toggleClass("collapsed"); $("#completed-versions").toggle()',
- :id => 'toggle-completed-versions', :class => 'collapsible collapsed' %>
-
-
<%= l(:label_no_data) %>
-<% else %> --
- <%= link_to_version version, :name => version_anchor(version) %> - <% if version.completed? %> - <%= format_date(version.effective_date) %> - <% elsif version.effective_date %> - <%= due_date_distance_in_words(version.effective_date) %> (<%= format_date(version.effective_date) %>) - <% end %> -
- - <%= render :partial => 'versions/overview', :locals => {:version => version} %> - <%= render(:partial => "wiki/content", :locals => {:content => version.wiki_page.content}) if version.wiki_page %> - <% if (issues = @issues_by_version[version]) && issues.size > 0 %> - <%= form_tag({}) do -%> -| <%= link_to_issue(issue, :project => (@project != issue.project)) %> | -
<%=h version.description %>
- <% if version.custom_field_values.any? %> --
- <% version.custom_field_values.each do |custom_value| %>
- <% if custom_value.value.present? %>
-
- <%=h custom_value.custom_field.name %>: <%=h show_value(custom_value) %> - <% end %> - <% end %> -
-
- <%= pagination_links_full @versions_pages%>
-
<%=l(:label_version_new)%>
- -<%= labelled_form_for @version, :url => project_versions_path(@project) do |f| %> -<%= render :partial => 'versions/form', :locals => { :f => f } %> -<%= submit_tag l(:button_create) %> -<% end %> diff --git a/trustie2/app/views/versions/new.js.erb b/trustie2/app/views/versions/new.js.erb deleted file mode 100644 index 114b9c7c5..000000000 --- a/trustie2/app/views/versions/new.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render :partial => 'versions/new_modal') %>'); -showModal('ajax-modal', '600px'); diff --git a/trustie2/app/views/versions/show.api.rsb b/trustie2/app/views/versions/show.api.rsb deleted file mode 100644 index 63bf2d379..000000000 --- a/trustie2/app/views/versions/show.api.rsb +++ /dev/null @@ -1,15 +0,0 @@ -api.version do - api.id @version.id - api.project(:id => @version.project_id, :name => @version.project.name) unless @version.project.nil? - - api.name @version.name - api.description @version.description - api.status @version.status - api.due_date @version.effective_date - api.sharing @version.sharing - - render_api_custom_values @version.custom_field_values, api - - api.created_on @version.created_on - api.updated_on @version.updated_on -end diff --git a/trustie2/app/views/versions/show.html.erb b/trustie2/app/views/versions/show.html.erb deleted file mode 100644 index 6517faca5..000000000 --- a/trustie2/app/views/versions/show.html.erb +++ /dev/null @@ -1,56 +0,0 @@ - -<%= h(@version.name) %>
- -| <%= l(:field_estimated_hours) %> | -<%= html_hours(l_hours(@version.estimated_hours)) %> | -
|---|---|
| <%= l(:label_spent_time) %> | -<%= html_hours(l_hours(@version.spent_hours)) %> | -
| <%= check_box_tag 'ids[]', issue.id, false, :id => nil %> | -<%= link_to_issue(issue, :project => (@project != issue.project)) %> | -
<%= l(:permission_add_issue_watchers) %>
- -<%= form_tag({:controller => 'watchers', - :action => (watched ? 'create' : 'append'), - :object_type => (watched && watched.class.name.underscore), - :object_id => watched, - :project_id => @project}, - :remote => true, - :method => :post, - :id => 'new-watcher-form') do %> - -<%= label_tag 'user_search', l(:label_user_search) %><%= text_field_tag 'user_search', nil %>
- <%= javascript_tag "observeSearchfield('user_search', 'users_for_watcher', '#{ escape_javascript url_for(:controller => 'watchers', - :action => 'autocomplete_for_user', - :object_type => (watched && watched.class.name.underscore), - :object_id => watched, - :project_id => @project) }')" %> - -<%= l(:label_issue_watchers) %> (<%= watched.watcher_users.size %>)
- -<%= watchers_list(watched) %> diff --git a/trustie2/app/views/watchers/append.js.erb b/trustie2/app/views/watchers/append.js.erb deleted file mode 100644 index 934865dfb..000000000 --- a/trustie2/app/views/watchers/append.js.erb +++ /dev/null @@ -1,4 +0,0 @@ -<% @users.each do |user| %> - $("#issue_watcher_user_ids_<%= user.id %>").remove(); -<% end %> -$('#watchers_inputs').append('<%= escape_javascript(watchers_checkboxes(nil, @users, true)) %>'); diff --git a/trustie2/app/views/watchers/autocomplete_for_user.html.erb b/trustie2/app/views/watchers/autocomplete_for_user.html.erb deleted file mode 100644 index a24d28eb4..000000000 --- a/trustie2/app/views/watchers/autocomplete_for_user.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= principals_check_box_tags 'watcher[user_ids][]', @users %> diff --git a/trustie2/app/views/watchers/create.js.erb b/trustie2/app/views/watchers/create.js.erb deleted file mode 100644 index 0f7e15a00..000000000 --- a/trustie2/app/views/watchers/create.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render(:partial => 'watchers/new', :locals => {:watched => @watched})) %>'); -$('#watchers').html('<%= escape_javascript(render(:partial => 'watchers/watchers', :locals => {:watched => @watched})) %>'); diff --git a/trustie2/app/views/watchers/destroy.js.erb b/trustie2/app/views/watchers/destroy.js.erb deleted file mode 100644 index e4d856549..000000000 --- a/trustie2/app/views/watchers/destroy.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#watchers').html('<%= escape_javascript(render(:partial => 'watchers/watchers', :locals => {:watched => @watched})) %>'); diff --git a/trustie2/app/views/watchers/new.js.erb b/trustie2/app/views/watchers/new.js.erb deleted file mode 100644 index 6b99f657e..000000000 --- a/trustie2/app/views/watchers/new.js.erb +++ /dev/null @@ -1,3 +0,0 @@ -$('#ajax-modal').html('<%= escape_javascript(render :partial => 'watchers/new', :locals => {:watched => @watched}) %>'); -showModal('ajax-modal', '400px'); -$('#ajax-modal').addClass('new-watcher'); diff --git a/trustie2/app/views/watchers/watch.js.erb b/trustie2/app/views/watchers/watch.js.erb deleted file mode 100644 index 104583fef..000000000 --- a/trustie2/app/views/watchers/watch.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#fans_num').html('<%= j(@user.watcher_users.count) %>') diff --git a/trustie2/app/views/welcome/_link_to_another.html.erb b/trustie2/app/views/welcome/_link_to_another.html.erb deleted file mode 100644 index f5f360d3e..000000000 --- a/trustie2/app/views/welcome/_link_to_another.html.erb +++ /dev/null @@ -1,6 +0,0 @@ - - \ No newline at end of file diff --git a/trustie2/app/views/welcome/_search_bar.html.erb b/trustie2/app/views/welcome/_search_bar.html.erb deleted file mode 100644 index 73a497835..000000000 --- a/trustie2/app/views/welcome/_search_bar.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -热门项目
- <%= link_to "更多>>", { :controller => 'projects', :action => 'index', :project_type => 0, :host => Setting.project_domain}, :target => "_blank" %> --
- <% find_miracle_project(10, 3).map do |project| %>
-
-
- - <%= image_tag(get_project_avatar(project), :class => "avatar-4") %> -- -- <%= link_to( project.name, project_path(project.id), :class => "d-g-blue d-p-project-name",:title => "#{project.name}" )%> - (<%= link_to "#{projectCount(project)}人", project_member_path(project) ,:course =>'0' %>) --- ><%=project.description.truncate(50, omission: '...')%> --- <%= content_tag "span", show_grade(project), - :style => "cursor: pointer; display: inline-block; float: right; color: #ec6300; ", - :title => "项目得分,综合考虑了项目的各项活动,反映了该项目的活跃程度", - :class => "tooltip", - :id => "tooltip-#{project.id}" %> - --
- <% end; reset_cycle %>
-
| 当前网站状态 | -活跃项目:<%=@projectCount%>个 | -私有项目: <%=@projectHidenCount%>个 | -开发者:<%=@allUsercount%>个 | -
Download Status:
-<%= @error.class %> \ No newline at end of file diff --git a/trustie2/config.ru b/trustie2/config.ru deleted file mode 100644 index baeb49715..000000000 --- a/trustie2/config.ru +++ /dev/null @@ -1,8 +0,0 @@ -# This file is used by Rack-based servers to start the application. - -require ::File.expand_path('../config/environment', __FILE__) - -map ActionController::Base.config.try(:relative_url_root) || "/" do -run RedmineApp::Application -end - diff --git a/trustie2/config/additional_environment.rb b/trustie2/config/additional_environment.rb deleted file mode 100644 index 6654da90f..000000000 --- a/trustie2/config/additional_environment.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Copy this file to additional_environment.rb and add any statements -# that need to be passed to the Rails::Initializer. `config` is -# available in this context. -# -# Example: -# -# config.log_level = :debug -# ... -# -#config.relative_url_root = '/socialforge' diff --git a/trustie2/config/additional_environment.rb.example b/trustie2/config/additional_environment.rb.example deleted file mode 100644 index 2a317a396..000000000 --- a/trustie2/config/additional_environment.rb.example +++ /dev/null @@ -1,10 +0,0 @@ -# Copy this file to additional_environment.rb and add any statements -# that need to be passed to the Rails::Initializer. `config` is -# available in this context. -# -# Example: -# -# config.log_level = :debug -# ... -# - diff --git a/trustie2/config/application.rb b/trustie2/config/application.rb deleted file mode 100644 index ff224231b..000000000 --- a/trustie2/config/application.rb +++ /dev/null @@ -1,61 +0,0 @@ -require File.expand_path('../boot', __FILE__) - -require 'rails/all' -require 'sprockets/railtie' - -if defined?(Bundler) - # If you precompile assets before deploying to production, use this line - Bundler.require(*Rails.groups(:assets => %w(development test))) - # If you want your assets lazily compiled in production, use this line - # Bundler.require(:default, :assets, Rails.env) -end - -module RedmineApp - class Application < Rails::Application - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - - # Custom directories with classes and modules you want to be autoloadable. - config.autoload_paths += %W(#{config.root}/lib) - - # Only load the plugins named here, in the order given (default is alphabetical). - # :all can be used as a placeholder for all plugins not explicitly named. - # config.plugins = [ :exception_notification, :ssl_requirement, :all ] - - # Activate observers that should always be running. - config.active_record.store_full_sti_class = true - config.active_record.default_timezone = :local - - # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. - # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. - # config.time_zone = 'Central Time (US & Canada)' - - # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. - # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] - config.i18n.default_locale = :zh - - # Configure the default encoding used in templates for Ruby 1.9. - config.encoding = "utf-8" - - # Configure sensitive parameters which will be filtered from the log file. - config.filter_parameters += [:password] - - # Enable the asset pipeline - config.assets.enabled = false - - # Version of your assets, change this if you want to expire all your assets - config.assets.version = '1.0' - - config.action_mailer.perform_deliveries = false - - # Do not include all helpers - config.action_controller.include_all_helpers = false - - config.session_store :cookie_store, :key => '_redmine_session', :expire_after => 60.minutes - - if File.exists?(File.join(File.dirname(__FILE__), 'additional_environment.rb')) - instance_eval File.read(File.join(File.dirname(__FILE__), 'additional_environment.rb')) - end - end -end diff --git a/trustie2/config/boot.rb b/trustie2/config/boot.rb deleted file mode 100644 index 4489e5868..000000000 --- a/trustie2/config/boot.rb +++ /dev/null @@ -1,6 +0,0 @@ -require 'rubygems' - -# Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) - -require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) diff --git a/trustie2/config/configuration.yml b/trustie2/config/configuration.yml deleted file mode 100644 index 2137e4f09..000000000 --- a/trustie2/config/configuration.yml +++ /dev/null @@ -1,200 +0,0 @@ -# = Redmine configuration file -# -# Each environment has it's own configuration options. If you are only -# running in production, only the production block needs to be configured. -# Environment specific configuration options override the default ones. -# -# Note that this file needs to be a valid YAML file. -# DO NOT USE TABS! Use 2 spaces instead of tabs for identation. -# -# == Outgoing email settings (email_delivery setting) -# -# === Common configurations -# -# ==== Sendmail command -# -# production: -# email_delivery: -# delivery_method: :sendmail -# -# ==== Simple SMTP server at localhost -# -# production: -# email_delivery: -# delivery_method: :smtp -# smtp_settings: -# address: smtp.163.com -# port: 25 -# -# ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com -# -# production: -# email_delivery: -# delivery_method: :smtp -# smtp_settings: -# address: smtp.gmail.com -# port: 587 -# authentication: :login -# domain: 'foo.com' -# user_name: senluowanxiangt@gmail.com -# password: 1913TXBja -# -# ==== SMTP server at example.com using PLAIN authentication -# -# production: -# email_delivery: -# delivery_method: :smtp -# smtp_settings: -# address: smtp.gmail.com -# port: 587 -# authentication: :plain -# domain: 'example.com' -# user_name: senluowanxiangt@gmail.com -# password: 1913TXBja -# -# ==== SMTP server at using TLS (GMail) -# -# This might require some additional configuration. See the guides at: -# http://www.redmine.org/projects/redmine/wiki/EmailConfiguration -# -# production: -# email_delivery: -# delivery_method: :smtp -# smtp_settings: -# enable_starttls_auto: true -# address: smtp.gmail.com -# port: 587 -# domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps -# authentication: :plain -# user_name: senluowanxiangt@gmail.com -# password: 1913TXBja -# -# -# === More configuration options -# -# See the "Configuration options" at the following website for a list of the -# full options allowed: -# -# http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer - - -# default configuration options for all environments -default: - # Outgoing emails configuration (see examples above) - email_delivery: - delivery_method: :smtp - smtp_settings: - - - - address: smtp.gmail.com - port: 587 - domain: smtp.gmail.com - authentication: :plain - user_name: trustieforge@gmail.com - password: '!@#$%^&*()' - - # Configuration of the autologin cookie. - # autologin_cookie_name: the name of the cookie (default: autologin) - # autologin_cookie_path: the cookie path (default: /) - # autologin_cookie_secure: true sets the cookie secure flag (default: false) - autologin_cookie_name: - autologin_cookie_path: - autologin_cookie_secure: - - # Configuration of SCM executable command. - # - # Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe) - # On Windows + CRuby, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work. - # - # On Windows + JRuby 1.6.2, path which contains spaces does not work. - # For example, "C:\Program Files\TortoiseHg\hg.exe". - # If you want to this feature, you need to install to the path which does not contains spaces. - # For example, "C:\TortoiseHg\hg.exe". - # - # Examples: - # scm_subversion_command: svn # (default: svn) - # scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg) - # scm_git_command: /usr/local/bin/git # (default: git) - # scm_cvs_command: cvs # (default: cvs) - # scm_bazaar_command: bzr.exe # (default: bzr) - # scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs) - # - scm_subversion_command: - scm_mercurial_command: - scm_git_command: - scm_cvs_command: - scm_bazaar_command: - scm_darcs_command: - - # Absolute path to the SCM commands errors (stderr) log file. - # The default is to log in the 'log' directory of your Redmine instance. - # Example: - # scm_stderr_log_file: /var/log/redmine_scm_stderr.log - scm_stderr_log_file: - - # Key used to encrypt sensitive data in the database (SCM and LDAP passwords). - # If you don't want to enable data encryption, just leave it blank. - # WARNING: losing/changing this key will make encrypted data unreadable. - # - # If you want to encrypt existing passwords in your database: - # * set the cipher key here in your configuration file - # * encrypt data using 'rake db:encrypt RAILS_ENV=production' - # - # If you have encrypted data and want to change this key, you have to: - # * decrypt data using 'rake db:decrypt RAILS_ENV=production' first - # * change the cipher key here in your configuration file - # * encrypt data using 'rake db:encrypt RAILS_ENV=production' - database_cipher_key: - - # Set this to false to disable plugins' assets mirroring on startup. - # You can use `rake redmine:plugins:assets` to manually mirror assets - # to public/plugin_assets when you install/upgrade a Redmine plugin. - # - #mirror_plugins_assets_on_startup: false - - # Your secret key for verifying cookie session data integrity. If you - # change this key, all old sessions will become invalid! Make sure the - # secret is at least 30 characters and all random, no regular words or - # you'll be exposed to dictionary attacks. - # - # If you have a load-balancing Redmine cluster, you have to use the - # same secret token on each machine. - #secret_token: 'change it to a long random string' - - # Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to - # the ImageMagick's `convert` binary. Used to generate attachment thumbnails. - imagemagick_convert_command: '/home/pdl/redmine-2.3.1-1/common/bin/convert' - - # Configuration of RMagcik font. - # - # Redmine uses RMagcik in order to export gantt png. - # You don't need this setting if you don't install RMagcik. - # - # In CJK (Chinese, Japanese and Korean), - # in order to show CJK characters correctly, - # you need to set this configuration. - # - # Because there is no standard font across platforms in CJK, - # you need to set a font installed in your server. - # - # This setting is not necessary in non CJK. - # - # Examples for Japanese: - # Windows: - # rmagick_font_path: C:\windows\fonts\msgothic.ttc - # Linux: - # rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf - # - rmagick_font_path: - - # Maximum number of simultaneous AJAX uploads - #max_concurrent_ajax_uploads: 2 - -# specific configuration options for production environment -# that overrides the default ones -production: - -# specific configuration options for development environment -# that overrides the default ones -development: diff --git a/trustie2/config/configuration.yml.example b/trustie2/config/configuration.yml.example deleted file mode 100644 index 27eb86f68..000000000 --- a/trustie2/config/configuration.yml.example +++ /dev/null @@ -1,206 +0,0 @@ -# = Redmine configuration file -# -# Each environment has it's own configuration options. If you are only -# running in production, only the production block needs to be configured. -# Environment specific configuration options override the default ones. -# -# Note that this file needs to be a valid YAML file. -# DO NOT USE TABS! Use 2 spaces instead of tabs for identation. -# -# == Outgoing email settings (email_delivery setting) -# -# === Common configurations -# -# ==== Sendmail command -# -# production: -# email_delivery: -# delivery_method: :sendmail -# -# ==== Simple SMTP server at localhost -# -# production: -# email_delivery: -# delivery_method: :smtp -# smtp_settings: -# address: "localhost" -# port: 25 -# -# ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com -# -# production: -# email_delivery: -# delivery_method: :smtp -# smtp_settings: -# address: "example.com" -# port: 25 -# authentication: :login -# domain: 'foo.com' -# user_name: 'myaccount' -# password: 'password' -# -# ==== SMTP server at example.com using PLAIN authentication -# -# production: -# email_delivery: -# delivery_method: :smtp -# smtp_settings: -# address: "example.com" -# port: 25 -# authentication: :plain -# domain: 'example.com' -# user_name: 'myaccount' -# password: 'password' -# -# ==== SMTP server at using TLS (GMail) -# -# This might require some additional configuration. See the guides at: -# http://www.redmine.org/projects/redmine/wiki/EmailConfiguration -# -# production: -# email_delivery: -# delivery_method: :smtp -# smtp_settings: -# enable_starttls_auto: true -# address: "smtp.gmail.com" -# port: 587 -# domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps -# authentication: :plain -# user_name: "your_email@gmail.com" -# password: "your_password" -# -# -# === More configuration options -# -# See the "Configuration options" at the following website for a list of the -# full options allowed: -# -# http://wiki.rubyonrails.org/rails/pages/HowToSendEmailsWithActionMailer - - -# default configuration options for all environments -default: - # Outgoing emails configuration (see examples above) - email_delivery: - delivery_method: :smtp - smtp_settings: - address: smtp.example.net - port: 25 - domain: example.net - authentication: :login - user_name: "redmine@example.net" - password: "redmine" - - # Absolute path to the directory where attachments are stored. - # The default is the 'files' directory in your Redmine instance. - # Your Redmine instance needs to have write permission on this - # directory. - # Examples: - # attachments_storage_path: /var/redmine/files - # attachments_storage_path: D:/redmine/files - attachments_storage_path: - - # Configuration of the autologin cookie. - # autologin_cookie_name: the name of the cookie (default: autologin) - # autologin_cookie_path: the cookie path (default: /) - # autologin_cookie_secure: true sets the cookie secure flag (default: false) - autologin_cookie_name: - autologin_cookie_path: - autologin_cookie_secure: - - # Configuration of SCM executable command. - # - # Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe) - # On Windows + CRuby, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work. - # - # On Windows + JRuby 1.6.2, path which contains spaces does not work. - # For example, "C:\Program Files\TortoiseHg\hg.exe". - # If you want to this feature, you need to install to the path which does not contains spaces. - # For example, "C:\TortoiseHg\hg.exe". - # - # Examples: - # scm_subversion_command: svn # (default: svn) - # scm_mercurial_command: C:\Program Files\TortoiseHg\hg.exe # (default: hg) - # scm_git_command: /usr/local/bin/git # (default: git) - # scm_cvs_command: cvs # (default: cvs) - # scm_bazaar_command: bzr.exe # (default: bzr) - # scm_darcs_command: darcs-1.0.9-i386-linux # (default: darcs) - # - scm_subversion_command: - scm_mercurial_command: - scm_git_command: - scm_cvs_command: - scm_bazaar_command: - scm_darcs_command: - - # Absolute path to the SCM commands errors (stderr) log file. - # The default is to log in the 'log' directory of your Redmine instance. - # Example: - # scm_stderr_log_file: /var/log/redmine_scm_stderr.log - scm_stderr_log_file: - - # Key used to encrypt sensitive data in the database (SCM and LDAP passwords). - # If you don't want to enable data encryption, just leave it blank. - # WARNING: losing/changing this key will make encrypted data unreadable. - # - # If you want to encrypt existing passwords in your database: - # * set the cipher key here in your configuration file - # * encrypt data using 'rake db:encrypt RAILS_ENV=production' - # - # If you have encrypted data and want to change this key, you have to: - # * decrypt data using 'rake db:decrypt RAILS_ENV=production' first - # * change the cipher key here in your configuration file - # * encrypt data using 'rake db:encrypt RAILS_ENV=production' - database_cipher_key: - - # Set this to false to disable plugins' assets mirroring on startup. - # You can use `rake redmine:plugins:assets` to manually mirror assets - # to public/plugin_assets when you install/upgrade a Redmine plugin. - # - #mirror_plugins_assets_on_startup: false - - # Your secret key for verifying cookie session data integrity. If you - # change this key, all old sessions will become invalid! Make sure the - # secret is at least 30 characters and all random, no regular words or - # you'll be exposed to dictionary attacks. - # - # If you have a load-balancing Redmine cluster, you have to use the - # same secret token on each machine. - #secret_token: 'change it to a long random string' - - # Absolute path (e.g. /usr/bin/convert, c:/im/convert.exe) to - # the ImageMagick's `convert` binary. Used to generate attachment thumbnails. - #imagemagick_convert_command: - - # Configuration of RMagcik font. - # - # Redmine uses RMagcik in order to export gantt png. - # You don't need this setting if you don't install RMagcik. - # - # In CJK (Chinese, Japanese and Korean), - # in order to show CJK characters correctly, - # you need to set this configuration. - # - # Because there is no standard font across platforms in CJK, - # you need to set a font installed in your server. - # - # This setting is not necessary in non CJK. - # - # Examples for Japanese: - # Windows: - # rmagick_font_path: C:\windows\fonts\msgothic.ttc - # Linux: - # rmagick_font_path: /usr/share/fonts/ipa-mincho/ipam.ttf - # - rmagick_font_path: - - # Maximum number of simultaneous AJAX uploads - #max_concurrent_ajax_uploads: 2 - -# specific configuration options for production environment -# that overrides the default ones -production: - -# specific configuration options for development environment -# that overrides the default ones -development: diff --git a/trustie2/config/database.yml.example b/trustie2/config/database.yml.example deleted file mode 100644 index 5b0657122..000000000 --- a/trustie2/config/database.yml.example +++ /dev/null @@ -1,53 +0,0 @@ -#source ~/.rvm/scripts/rvm# Default setup is given for MySQL with ruby1.9. If you're running Redmine -#source ~/.rvm/scripts/rvm# Default setup is given for MySQL with ruby1.9. If you're running Redmine -# with MySQL and ruby1.8, replace the adapter name with `mysql`. -# Examples for PostgreSQL, SQLite3 and SQL Server can be found at the end. -# Line indentation must be 2 spaces (no tabs). - -production: - adapter: mysql2 - database: ossean_production - host: localhost - username: root - password: "" - encoding: utf8 - -development: - adapter: mysql2 - database: ossean_production - host: localhost - username: root - password: "123456" - encoding: utf8 - -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. -test: - adapter: mysql2 - database: redmine_test - host: 10.107.17.20 - username: root - password: "1234" - encoding: utf8 - -# PostgreSQL configuration example -#production: -# adapter: postgresql -# database: redmine -# host: localhost -# username: postgres -# password: "postgres" - -# SQLite3 configuration example -#production: -# adapter: sqlite3 -# database: db/redmine.sqlite3 - -# SQL Server configuration example -#production: -# adapter: sqlserver -# database: redmine -# host: localhost -# username: jenkins -# password: jenkins diff --git a/trustie2/config/environment.rb b/trustie2/config/environment.rb deleted file mode 100644 index 1d9a39669..000000000 --- a/trustie2/config/environment.rb +++ /dev/null @@ -1,14 +0,0 @@ -# Load the rails application -require File.expand_path('../application', __FILE__) - -# Make sure there's no plugin in vendor/plugin before starting -vendor_plugins_dir = File.join(Rails.root, "vendor", "plugins") -if Dir.glob(File.join(vendor_plugins_dir, "*")).any? - $stderr.puts "Plugins in vendor/plugins (#{vendor_plugins_dir}) are no longer allowed. " + - "Please, put your Redmine plugins in the `plugins` directory at the root of your " + - "Redmine directory (#{File.join(Rails.root, "plugins")})" - exit 1 -end - -# Initialize the rails application -RedmineApp::Application.initialize! diff --git a/trustie2/config/environments/development.rb b/trustie2/config/environments/development.rb deleted file mode 100644 index 9d3cbf244..000000000 --- a/trustie2/config/environments/development.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Settings specified here will take precedence over those in config/application.rb -RedmineApp::Application.configure do - # In the development environment your application's code is reloaded on - # every request. This slows down response time but is perfect for development - # since you don't have to restart the webserver when you make code changes. - config.cache_classes = false - - # Log error messages when you accidentally call methods on nil. - config.whiny_nils = true - - # Show full error reports and disable caching - config.consider_all_requests_local = true - config.action_controller.perform_caching = false - - # Don't care if the mailer can't send - config.action_mailer.raise_delivery_errors = false - - config.active_support.deprecation = :log -end diff --git a/trustie2/config/environments/production.rb b/trustie2/config/environments/production.rb deleted file mode 100644 index ab4cd4011..000000000 --- a/trustie2/config/environments/production.rb +++ /dev/null @@ -1,32 +0,0 @@ -# Settings specified here will take precedence over those in config/application.rb -RedmineApp::Application.configure do - # The production environment is meant for finished, "live" apps. - # Code is not reloaded between requests - config.cache_classes = true - - ##### - # Customize the default logger (http://ruby-doc.org/core/classes/Logger.html) - # - # Use a different logger for distributed setups - # config.logger = SyslogLogger.new - # - # Rotate logs bigger than 1MB, keeps no more than 7 rotated logs around. - # When setting a new Logger, make sure to set it's log level too. - # - # config.logger = Logger.new(config.log_path, 7, 1048576) - # config.logger.level = Logger::INFO - - # Full error reports are disabled and caching is turned on - config.action_controller.perform_caching = true - - # Enable serving of images, stylesheets, and javascripts from an asset server - # config.action_controller.asset_host = "http://assets.example.com" - - # Disable delivery errors if you bad email addresses should just be ignored - config.action_mailer.raise_delivery_errors = false - - # No email in production log - config.action_mailer.logger = nil - - config.active_support.deprecation = :log -end diff --git a/trustie2/config/environments/test.rb b/trustie2/config/environments/test.rb deleted file mode 100644 index b4696385e..000000000 --- a/trustie2/config/environments/test.rb +++ /dev/null @@ -1,30 +0,0 @@ -# Settings specified here will take precedence over those in config/application.rb -RedmineApp::Application.configure do - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true - - # Log error messages when you accidentally call methods on nil. - config.whiny_nils = true - - # Show full error reports and disable caching - #config.action_controller.consider_all_requests_local = true - config.action_controller.perform_caching = false - - config.action_mailer.perform_deliveries = true - - # Tell Action Mailer not to deliver emails to the real world. - # The :test delivery method accumulates sent emails in the - # ActionMailer::Base.deliveries array. - config.action_mailer.delivery_method = :test - - # Skip protect_from_forgery in requests - # http://m.onkey.org/2007/9/28/csrf-protection-for-your-existing-rails-application - config.action_controller.allow_forgery_protection = false - - config.active_support.deprecation = :log - - config.secret_token = 'a secret token for running the tests' -end diff --git a/trustie2/config/environments/test_pgsql.rb b/trustie2/config/environments/test_pgsql.rb deleted file mode 100644 index 45cb09bdd..000000000 --- a/trustie2/config/environments/test_pgsql.rb +++ /dev/null @@ -1 +0,0 @@ -instance_eval File.read(File.join(File.dirname(__FILE__), 'test.rb')) diff --git a/trustie2/config/environments/test_sqlite3.rb b/trustie2/config/environments/test_sqlite3.rb deleted file mode 100644 index 45cb09bdd..000000000 --- a/trustie2/config/environments/test_sqlite3.rb +++ /dev/null @@ -1 +0,0 @@ -instance_eval File.read(File.join(File.dirname(__FILE__), 'test.rb')) diff --git a/trustie2/config/initializers/00-core_plugins.rb b/trustie2/config/initializers/00-core_plugins.rb deleted file mode 100644 index 004c2a1f6..000000000 --- a/trustie2/config/initializers/00-core_plugins.rb +++ /dev/null @@ -1,15 +0,0 @@ -# Loads the core plugins located in lib/plugins -Dir.glob(File.join(Rails.root, "lib/plugins/*")).sort.each do |directory| - if File.directory?(directory) - lib = File.join(directory, "lib") - if File.directory?(lib) - $:.unshift lib - ActiveSupport::Dependencies.autoload_paths += [lib] - end - initializer = File.join(directory, "init.rb") - if File.file?(initializer) - config = config = RedmineApp::Application.config - eval(File.read(initializer), binding, initializer) - end - end -end diff --git a/trustie2/config/initializers/10-patches.rb b/trustie2/config/initializers/10-patches.rb deleted file mode 100644 index 3996ef48f..000000000 --- a/trustie2/config/initializers/10-patches.rb +++ /dev/null @@ -1,167 +0,0 @@ -require 'active_record' - -module ActiveRecord - class Base - include Redmine::I18n - # Translate attribute names for validation errors display - def self.human_attribute_name(attr, *args) - attr = attr.to_s.sub(/_id$/, '') - - l("field_#{name.underscore.gsub('/', '_')}_#{attr}", :default => ["field_#{attr}".to_sym, attr]) - end - end - - # Undefines private Kernel#open method to allow using `open` scopes in models. - # See Defect #11545 (http://www.redmine.org/issues/11545) for details. - class Base - class << self - undef open - end - end - class Relation ; undef open ; end -end - -module ActionView - module Helpers - module DateHelper - # distance_of_time_in_words breaks when difference is greater than 30 years - def distance_of_date_in_words(from_date, to_date = 0, options = {}) - from_date = from_date.to_date if from_date.respond_to?(:to_date) - to_date = to_date.to_date if to_date.respond_to?(:to_date) - distance_in_days = (to_date - from_date).abs - - I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale| - case distance_in_days - when 0..60 then locale.t :x_days, :count => distance_in_days.round - when 61..720 then locale.t :about_x_months, :count => (distance_in_days / 30).round - else locale.t :over_x_years, :count => (distance_in_days / 365).floor - end - end - end - end - end - - class Resolver - def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[]) - cached(key, [name, prefix, partial], details, locals) do - if details[:formats] & [:xml, :json] - details = details.dup - details[:formats] = details[:formats].dup + [:api] - end - find_templates(name, prefix, partial, details) - end - end - end -end - -# Do not HTML escape text templates -module ActionView - class Template - module Handlers - class ERB - def call(template) - if template.source.encoding_aware? - # First, convert to BINARY, so in case the encoding is - # wrong, we can still find an encoding tag - # (<%# encoding %>) inside the String using a regular - # expression - template_source = template.source.dup.force_encoding("BINARY") - - erb = template_source.gsub(ENCODING_TAG, '') - encoding = $2 - - erb.force_encoding valid_encoding(template.source.dup, encoding) - - # Always make sure we return a String in the default_internal - erb.encode! - else - erb = template.source.dup - end - - self.class.erb_implementation.new( - erb, - :trim => (self.class.erb_trim_mode == "-"), - :escape => template.identifier =~ /\.text/ # only escape HTML templates - ).src - end - end - end - end -end - -ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| html_tag || ''.html_safe } - -require 'mail' - -module DeliveryMethods - class AsyncSMTP < ::Mail::SMTP - def deliver!(*args) - Thread.start do - super *args - end - end - end - - class AsyncSendmail < ::Mail::Sendmail - def deliver!(*args) - Thread.start do - super *args - end - end - end - - class TmpFile - def initialize(*args); end - - def deliver!(mail) - dest_dir = File.join(Rails.root, 'tmp', 'emails') - Dir.mkdir(dest_dir) unless File.directory?(dest_dir) - File.open(File.join(dest_dir, mail.message_id.gsub(/[<>]/, '') + '.eml'), 'wb') {|f| f.write(mail.encoded) } - end - end -end - -ActionMailer::Base.add_delivery_method :async_smtp, DeliveryMethods::AsyncSMTP -ActionMailer::Base.add_delivery_method :async_sendmail, DeliveryMethods::AsyncSendmail -ActionMailer::Base.add_delivery_method :tmp_file, DeliveryMethods::TmpFile - -# Changes how sent emails are logged -# Rails doesn't log cc and bcc which is misleading when using bcc only (#12090) -module ActionMailer - class LogSubscriber < ActiveSupport::LogSubscriber - def deliver(event) - recipients = [:to, :cc, :bcc].inject("") do |s, header| - r = Array.wrap(event.payload[header]) - if r.any? - s << "\n #{header}: #{r.join(', ')}" - end - s - end - info("\nSent email \"#{event.payload[:title]}\" (%1.fms)#{recipients}" % event.duration) - debug(event.payload[:mail]) - end - end -end - -module ActionController - module MimeResponds - class Collector - def api(&block) - any(:xml, :json, &block) - end - end - end -end - -module ActionController - class Base - # Displays an explicit message instead of a NoMethodError exception - # when trying to start Redmine with an old session_store.rb - # TODO: remove it in a later version - def self.session=(*args) - $stderr.puts "Please remove config/initializers/session_store.rb and run `rake generate_secret_token`.\n" + - "Setting the session secret with ActionController.session= is no longer supported in Rails 3." - exit 1 - end - end -end diff --git a/trustie2/config/initializers/20-mime_types.rb b/trustie2/config/initializers/20-mime_types.rb deleted file mode 100644 index cfd35a3e9..000000000 --- a/trustie2/config/initializers/20-mime_types.rb +++ /dev/null @@ -1,4 +0,0 @@ -# Add new mime types for use in respond_to blocks: - -Mime::SET << Mime::CSV unless Mime::SET.include?(Mime::CSV) - diff --git a/trustie2/config/initializers/30-redmine.rb b/trustie2/config/initializers/30-redmine.rb deleted file mode 100644 index 1018ca18c..000000000 --- a/trustie2/config/initializers/30-redmine.rb +++ /dev/null @@ -1,15 +0,0 @@ -I18n.default_locale = 'en' -I18n.backend = Redmine::I18n::Backend.new - -require 'redmine' - -# Load the secret token from the Redmine configuration file -secret = Redmine::Configuration['secret_token'] -if secret.present? - RedmineApp::Application.config.secret_token = secret -end - -Redmine::Plugin.load -unless Redmine::Configuration['mirror_plugins_assets_on_startup'] == false - Redmine::Plugin.mirror_assets -end diff --git a/trustie2/config/initializers/backtrace_silencers.rb b/trustie2/config/initializers/backtrace_silencers.rb deleted file mode 100644 index 370315de2..000000000 --- a/trustie2/config/initializers/backtrace_silencers.rb +++ /dev/null @@ -1,7 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. -# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } - -# You can also remove all the silencers if you're trying do debug a problem that might steem from framework code. -# Rails.backtrace_cleaner.remove_silencers! diff --git a/trustie2/config/initializers/inflections.rb b/trustie2/config/initializers/inflections.rb deleted file mode 100644 index d531b8bb8..000000000 --- a/trustie2/config/initializers/inflections.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Add new inflection rules using the following format -# (all these examples are active by default): -# ActiveSupport::Inflector.inflections do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' -# inflect.uncountable %w( fish sheep ) -# end diff --git a/trustie2/config/initializers/secret_token.rb b/trustie2/config/initializers/secret_token.rb deleted file mode 100644 index 68cbf0aea..000000000 --- a/trustie2/config/initializers/secret_token.rb +++ /dev/null @@ -1,11 +0,0 @@ -# This file was generated by 'rake generate_secret_token', and should -# not be made visible to public. -# If you have a load-balancing Redmine cluster, you will need to use the -# same version of this file on each machine. And be sure to restart your -# server when you modify this file. -# -# Your secret key for verifying cookie session data integrity. If you -# change this key, all old sessions will become invalid! Make sure the -# secret is at least 30 characters and all random, no regular words or -# you'll be exposed to dictionary attacks. -RedmineApp::Application.config.secret_token = '8109e793d9c8233f79ebe3aa09c756d54bf6bffe7043ce1c4bd73928864c72a0b323bc3ccc82493e' diff --git a/trustie2/config/initializers/seems_rateable.rb b/trustie2/config/initializers/seems_rateable.rb deleted file mode 100644 index 2391948fa..000000000 --- a/trustie2/config/initializers/seems_rateable.rb +++ /dev/null @@ -1,4 +0,0 @@ -#SeemsRateable engine Initializer - -#Configure owner class of the given ratings -SeemsRateable::Engine.config.owner_class = "User" diff --git a/trustie2/config/locales/en.yml b/trustie2/config/locales/en.yml deleted file mode 100644 index 5c0d34a3e..000000000 --- a/trustie2/config/locales/en.yml +++ /dev/null @@ -1,1622 +0,0 @@ -en: - # Text direction: Left-to-Right (ltr) or Right-to-Left (rtl) - direction: ltr - date: - formats: - # Use the strftime parameters for formats. - # When no format has been given, it uses default. - # You can provide other formats here if you like! - default: "%m/%d/%Y" - short: "%b %d" - long: "%B %d, %Y" - - day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday] - abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat] - - # Don't forget the nil at the beginning; there's no such thing as a 0th month - month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December] - abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec] - # Used in date_select and datime_select. - order: - - :year - - :month - - :day - - time: - formats: - default: "%m/%d/%Y %I:%M %p" - time: "%I:%M %p" - short: "%d %b %H:%M" - long: "%B %d, %Y %H:%M" - am: "am" - pm: "pm" - - datetime: - distance_in_words: - half_a_minute: "half a minute" - less_than_x_seconds: - one: "less than 1 second" - other: "less than %{count} seconds" - x_seconds: - one: "1 second" - other: "%{count} seconds" - less_than_x_minutes: - one: "less than a minute" - other: "less than %{count} minutes" - x_minutes: - one: "1 minute" - other: "%{count} minutes" - about_x_hours: - one: "about 1 hour" - other: "about %{count} hours" - x_hours: - one: "1 hour" - other: "%{count} hours" - x_days: - one: "1 day" - other: "%{count} days" - about_x_months: - one: "about 1 month" - other: "about %{count} months" - x_months: - one: "1 month" - other: "%{count} months" - about_x_years: - one: "about 1 year" - other: "about %{count} years" - over_x_years: - one: "over 1 year" - other: "over %{count} years" - almost_x_years: - one: "almost 1 year" - other: "almost %{count} years" - - number: - format: - separator: "." - delimiter: "" - precision: 3 - - human: - format: - delimiter: "" - precision: 3 - storage_units: - format: "%n %u" - units: - byte: - one: "Byte" - other: "Bytes" - kb: "KB" - mb: "MB" - gb: "GB" - tb: "TB" - -# Used in array.to_sentence. - support: - array: - sentence_connector: "and" - skip_last_comma: false - - activerecord: - errors: - template: - header: - one: "1 error prohibited this %{model} from being saved" - other: "%{count} errors prohibited this %{model} from being saved" - messages: - inclusion: "is not included in the list" - exclusion: "is reserved" - invalid: "is invalid" - confirmation: "doesn't match confirmation" - accepted: "must be accepted" - empty: "can't be empty" - blank: "can't be blank" - too_long: "is too long (maximum is %{count} characters)" - too_short: "is too short (minimum is %{count} characters)" - wrong_length: "is the wrong length (should be %{count} characters)" - taken: "has already been taken" - not_a_number: "is not a number" - not_a_date: "is not a valid date" - greater_than: "must be greater than %{count}" - greater_than_or_equal_to: "must be greater than or equal to %{count}" - equal_to: "must be equal to %{count}" - less_than: "must be less than %{count}" - less_than_or_equal_to: "must be less than or equal to %{count}" - odd: "must be odd" - even: "must be even" - greater_than_start_date: "must be greater than start date" - 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" - - actionview_instancetag_blank_option: Please select - - attachment_all: "All" - attachment_browse: "Attachment Content Browse" - attachment_sufix_browse: "Attachment Type Browse" - attachment_type: "Attachment Type" - general_text_No: 'No' - general_text_Yes: 'Yes' - general_text_no: 'no' - general_text_yes: 'yes' - general_lang_name: 'English' - general_csv_separator: ',' - general_csv_decimal_separator: '.' - general_csv_encoding: ISO-8859-1 - general_pdf_encoding: UTF-8 - general_first_day_of_week: '7' - - label_approve: Approve - label_refusal: Refusal - notice_account_updated: Account was successfully updated. - notice_account_invalid_creditentials: Invalid user or password - notice_account_password_updated: Password was successfully updated. - notice_account_wrong_password: Wrong password - notice_account_register_done: Account was successfully created. To activate your account, click on the link that was emailed to you. - notice_account_unknown_email: Unknown user. - notice_can_t_change_password: This account uses an external authentication source. Impossible to change the password. - notice_account_lost_email_sent: An email with instructions to choose a new password has been sent to you. - notice_account_activated: Your account has been activated. You can now log in. - notice_successful_create: Successful creation. - notice_successful_update: Successful update. - notice_successful_delete: Successful deletion. - notice_failed_delete: Successful failure. - notice_successful_connection: Successful connection. - notice_file_not_found: The page you were trying to access doesn't exist or has been removed. - notice_locking_conflict: Data has been updated by another user. - notice_not_authorized: You are not authorized to access this page. - notice_not_authorized_archived_project: The project you're trying to access has been archived. - notice_email_sent: "An email was sent to %{value}" - notice_email_error: "An error occurred while sending mail (%{value})" - notice_feeds_access_key_reseted: Your RSS access key was reset. - notice_api_access_key_reseted: Your API access key was reset. - notice_failed_to_save_issues: "Failed to save %{count} issue(s) on %{total} selected: %{ids}." - notice_failed_to_save_time_entries: "Failed to save %{count} time entrie(s) on %{total} selected: %{ids}." - notice_failed_to_save_members: "Failed to save member(s): %{errors}." - notice_no_issue_selected: "No issue is selected! Please, check the issues you want to edit." - notice_account_pending: "Your account was created and is now pending administrator approval." - notice_default_data_loaded: Default configuration successfully loaded. - notice_unable_delete_version: Unable to delete version. - notice_unable_delete_time_entry: Unable to delete time log entry. - notice_issue_done_ratios_updated: Issue done ratios updated. - notice_gantt_chart_truncated: "The chart was truncated because it exceeds the maximum number of items that can be displayed (%{max})" - notice_issue_successful_create: "Issue %{id} created." - notice_issue_update_conflict: "The issue has been updated by an other user while you were editing it." - notice_account_deleted: "Your account has been permanently deleted." - notice_user_successful_create: "User %{id} created." - - error_can_t_load_default_data: "Default configuration could not be loaded: %{value}" - error_scm_not_found: "The entry or revision was not found in the repository." - error_scm_command_failed: "An error occurred when trying to access the repository: %{value}" - error_scm_annotate: "The entry does not exist or cannot be annotated." - error_scm_annotate_big_text_file: "The entry cannot be annotated, as it exceeds the maximum text file size." - error_issue_not_found_in_project: 'The issue was not found or does not belong to this project' - error_no_tracker_in_project: 'No tracker is associated to this project. Please check the Project settings.' - error_no_default_issue_status: 'No default issue status is defined. Please check your configuration (Go to "Administration -> Issue statuses").' - error_can_not_delete_custom_field: Unable to delete custom field - error_can_not_delete_tracker: "This tracker contains issues and cannot be deleted." - error_can_not_remove_role: "This role is in use and cannot be deleted." - error_can_not_reopen_issue_on_closed_version: 'An issue assigned to a closed version cannot be reopened' - error_can_not_archive_project: This project cannot be archived - error_issue_done_ratios_not_updated: "Issue done ratios not updated." - error_workflow_copy_source: 'Please select a source tracker or role' - error_workflow_copy_target: 'Please select target tracker(s) and role(s)' - error_unable_delete_issue_status: 'Unable to delete issue status' - error_unable_to_connect: "Unable to connect (%{value})" - error_attachment_too_big: "This file cannot be uploaded because it exceeds the maximum allowed file size (%{max_size})" - error_session_expired: "Your session has expired. Please login again." - warning_attachments_not_saved: "%{count} file(s) could not be saved." - - mail_title_lost_password: "Your %{value} password" - mail_body_lost_password: 'To change your password, click on the following link:' - mail_title_register: "Your %{value} account activation" - mail_body_register: 'To activate your account, click on the following link:' - mail_body_account_information_external: "You can use your %{value} account to log in." - mail_body_account_information: Your account information - mail_title_account_activation_request: "%{value} account activation request" - mail_body_account_activation_request: "A new user (%{value}) has registered. The account is pending your approval:" - mail_title_reminder: "%{count} issue(s) due in the next %{days} days" - mail_body_reminder: "%{count} issue(s) that are assigned to you are due in the next %{days} days:" - mail_title_wiki_content_added: "'%{id}' wiki page has been added" - mail_body_wiki_content_added: "The '%{id}' wiki page has been added by %{author}." - mail_title_wiki_content_updated: "'%{id}' wiki page has been updated" - mail_body_wiki_content_updated: "The '%{id}' wiki page has been updated by %{author}." - - field_name: Name - field_description: Description - field_summary: Summary - field_is_required: Required - field_firstname: First name - field_lastname: Last name - field_mail: Email - field_job_category: Job category # added by bai - field_filename: File - field_filesize: Size - field_downloads: Downloads - field_author: Author - field_created_on: Created - field_updated_on: Updated - field_closed_on: Closed - field_field_format: Format - field_is_for_all: For all projects - field_possible_values: Possible values - field_regexp: Regular expression - field_min_length: Minimum length - field_max_length: Maximum length - field_value: Value - field_category: Category - field_title: Title - field_project: Project - field_issue: Issue - field_status: Status - field_notes: Notes - field_is_closed: Issue closed - field_is_default: Default value - field_tracker: Tracker - field_title: title - field_due_date: Due date - field_assigned_to: Assignee - field_priority: Priority - field_fixed_version: Target version - field_user: User - field_principal: Principal - field_role: Role - field_homepage: Homepage - field_is_public: Public - field_parent: Subproject of - field_is_in_roadmap: Issues displayed in roadmap - field_login: Login - field_mail_notification: Email notifications - field_admin: Administrator - field_last_login_on: Last connection - field_language: Language - field_effective_date: Date - field_password: Password - field_new_password: New password - field_password_confirmation: Confirmation - field_version: Version - field_type: Type - field_host: Host - field_port: Port - field_account: Account - field_base_dn: Base DN - field_attr_login: Login attribute - field_attr_firstname: Firstname attribute - field_attr_lastname: Lastname attribute - field_attr_mail: Email attribute - field_onthefly: On-the-fly user creation - field_start_date: Start date - field_done_ratio: "% Done" - field_auth_source: Authentication mode - field_hide_mail: Hide my email address - field_comments: Comment - field_url: URL - field_start_page: Start page - field_subproject: Subproject - field_hours: Hours - field_activity: Activity - field_spent_on: Date - field_identifier: Identifier - field_is_filter: Used as a filter - field_issue_to: Related issue - field_delay: Delay - field_assignable: Issues can be assigned to this role - field_redirect_existing_links: Redirect existing links - field_estimated_hours: Estimated time - field_column_names: Columns - field_time_entries: Log time - field_time_zone: Time zone - field_searchable: Searchable - field_default_value: Default value - field_comments_sorting: Display comments - field_parent_title: Parent page - field_editable: Editable - field_watcher: Watcher - field_identity_url: OpenID URL - field_content: Content - field_group_by: Group results by - field_sharing: Sharing - field_parent_issue: Parent task - field_member_of_group: "Assignee's group" - field_assigned_to_role: "Assignee's role" - field_text: Text field - field_visible: Visible - field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text" - field_issues_visibility: Issues visibility - field_is_private: Private - field_commit_logs_encoding: Commit messages encoding - field_scm_path_encoding: Path encoding - field_path_to_repository: Path to repository - field_root_directory: Root directory - field_cvsroot: CVSROOT - field_cvs_module: Module - field_repository_is_default: Main repository - field_multiple: Multiple values - field_auth_source_ldap_filter: LDAP filter - field_core_fields: Standard fields - field_timeout: "Timeout (in seconds)" - field_board_parent: Parent forum - field_private_notes: Private notes - field_inherit_members: Inherit members - - setting_app_title: Application title - setting_app_subtitle: Application subtitle - setting_welcome_text: Welcome text - setting_default_language: Default language - setting_login_required: Authentication required - setting_self_registration: Self-registration - setting_attachment_max_size: Maximum attachment size - setting_issues_export_limit: Issues export limit - setting_mail_from: Emission email address - setting_bcc_recipients: Blind carbon copy recipients (bcc) - setting_plain_text_mail: Plain text mail (no HTML) - setting_host_name: Host name and path - setting_text_formatting: Text formatting - setting_wiki_compression: Wiki history compression - setting_feeds_limit: Maximum number of items in Atom feeds - setting_default_projects_public: New projects are public by default - setting_autofetch_changesets: Fetch commits automatically - setting_sys_api_enabled: Enable WS for repository management - setting_commit_ref_keywords: Referencing keywords - setting_commit_fix_keywords: Fixing keywords - setting_autologin: Autologin - setting_date_format: Date format - setting_time_format: Time format - setting_cross_project_issue_relations: Allow cross-project issue relations - setting_cross_project_subtasks: Allow cross-project subtasks - setting_issue_list_default_columns: Default columns displayed on the issue list - setting_repositories_encodings: Attachments and repositories encodings - setting_emails_header: Email header - setting_emails_footer: Email footer - setting_protocol: Protocol - setting_per_page_options: Objects per page options - setting_user_format: Users display format - setting_activity_days_default: Days displayed on project activity - setting_display_subprojects_issues: Display subprojects issues on main projects by default - setting_enabled_scm: Enabled SCM - setting_mail_handler_body_delimiters: "Truncate emails after one of these lines" - setting_mail_handler_api_enabled: Enable WS for incoming emails - setting_mail_handler_api_key: API key - setting_sequential_project_identifiers: Generate sequential project identifiers - setting_gravatar_enabled: Use Gravatar user icons - setting_gravatar_default: Default Gravatar image - setting_diff_max_lines_displayed: Maximum number of diff lines displayed - setting_file_max_size_displayed: Maximum size of text files displayed inline - setting_repository_log_display_limit: Maximum number of revisions displayed on file log - setting_openid: Allow OpenID login and registration - setting_password_min_length: Minimum password length - setting_new_project_user_role_id: Role given to a non-admin user who creates a project - setting_default_projects_modules: Default enabled modules for new projects - setting_issue_done_ratio: Calculate the issue done ratio with - setting_issue_done_ratio_issue_field: Use the issue field - setting_issue_done_ratio_issue_status: Use the issue status - setting_start_of_week: Start calendars on - setting_rest_api_enabled: Enable REST web service - setting_cache_formatted_text: Cache formatted text - setting_default_notification_option: Default notification option - setting_commit_logtime_enabled: Enable time logging - setting_commit_logtime_activity_id: Activity for logged time - setting_gantt_items_limit: Maximum number of items displayed on the gantt chart - setting_issue_group_assignment: Allow issue assignment to groups - setting_default_issue_start_date_to_creation_date: Use current date as start date for new issues - setting_commit_cross_project_ref: Allow issues of all the other projects to be referenced and fixed - setting_unsubscribe: Allow users to delete their own account - setting_session_lifetime: Session maximum lifetime - setting_session_timeout: Session inactivity timeout - setting_thumbnails_enabled: Display attachment thumbnails - setting_thumbnails_size: Thumbnails size (in pixels) - setting_non_working_week_days: Non-working days - setting_jsonp_enabled: Enable JSONP support - setting_default_projects_tracker_ids: Default trackers for new projects - - permission_add_project: Create project - permission_add_subprojects: Create subprojects - permission_edit_project: Edit project - permission_close_project: Close / reopen the project - permission_select_project_modules: Select project modules - permission_manage_members: Manage members - permission_manage_project_activities: Manage project activities - permission_manage_versions: Manage versions - permission_manage_categories: Manage issue categories - permission_view_issues: View Issues - permission_add_issues: Add issues - permission_edit_issues: Edit issues - permission_manage_issue_relations: Manage issue relations - permission_set_issues_private: Set issues public or private - permission_set_own_issues_private: Set own issues public or private - permission_add_issue_notes: Add notes - permission_edit_issue_notes: Edit notes - permission_edit_own_issue_notes: Edit own notes - permission_view_private_notes: View private notes - permission_set_notes_private: Set notes as private - permission_move_issues: Move issues - permission_delete_issues: Delete issues - permission_manage_public_queries: Manage public queries - permission_save_queries: Save queries - permission_view_gantt: View gantt chart - permission_view_calendar: View calendar - permission_view_issue_watchers: View watchers list - permission_add_issue_watchers: Add watchers - permission_delete_issue_watchers: Delete watchers - permission_log_time: Log spent time - permission_view_time_entries: View spent time - permission_edit_time_entries: Edit time logs - permission_edit_own_time_entries: Edit own time logs - permission_manage_news: Manage news - permission_comment_news: Comment news - permission_view_documents: View documents - permission_add_documents: Add documents - permission_edit_documents: Edit documents - permission_delete_documents: Delete documents - permission_manage_files: Manage files - permission_view_files: View files - permission_manage_wiki: Manage wiki - permission_rename_wiki_pages: Rename wiki pages - permission_delete_wiki_pages: Delete wiki pages - permission_view_wiki_pages: View wiki - permission_view_wiki_edits: View wiki history - permission_edit_wiki_pages: Edit wiki pages - permission_delete_wiki_pages_attachments: Delete attachments - permission_protect_wiki_pages: Protect wiki pages - permission_manage_repository: Manage repository - permission_browse_repository: Browse repository - permission_view_changesets: View changesets - permission_commit_access: Commit access - permission_manage_boards: Manage forums - permission_view_messages: View messages - permission_add_messages: Post messages - permission_edit_messages: Edit messages - permission_edit_own_messages: Edit own messages - permission_delete_messages: Delete messages - permission_delete_own_messages: Delete own messages - permission_export_wiki_pages: Export wiki pages - permission_manage_subtasks: Manage subtasks - permission_manage_related_issues: Manage related issues - - project_module_issue_tracking: Issue tracking - project_module_time_tracking: Time tracking - project_module_news: News - project_module_documents: Documents - project_module_files: Files - project_module_wiki: Wiki - project_module_repository: Repository - project_module_boards: Forums - project_module_calendar: Calendar - project_module_gantt: Gantt - - label_user: User - label_user_plural: Users - label_user_new: New user - label_user_anonymous: Anonymous - label_project: Project - label_activity_project: 'Project: ' #added by bai - label_project_new: New project - label_project_plural: Projects - label_project_deposit: Projects - label_x_projects: - zero: no projects - one: 1 project - other: "%{count} projects" - label_project_all: All Projects - label_project_latest: Latest projects - label_issue: Issue - label_issue_new: New issue - label_issue_plural: Issues - label_issue_view_all: View all issues - label_issues_by: "Issues by %{value}" - label_issue_added: Issue added - label_issue_updated: Issue updated - label_issue_note_added: Note added - label_issue_status_updated: Status updated - label_issue_priority_updated: Priority updated - label_document: Document - label_document_new: New document - label_document_plural: Documents - label_document_added: Document added - label_role: Role - label_role_plural: Roles - label_role_new: New role - label_role_and_permissions: Roles and permissions - label_role_anonymous: Anonymous - label_role_non_member: Non member - label_member: Members - label_member_new: New member - label_member_plural: Members - label_tracker: Tracker - label_tracker_plural: Trackers - label_tracker_new: New tracker - label_workflow: Workflow - label_issue_status: Issue status - label_issue_status_plural: Issue statuses - label_issue_status_new: New status - label_issue_category: Issue category - label_issue_category_plural: Issue categories - label_issue_category_new: New category - label_custom_field: Custom field - label_custom_field_plural: Custom fields - label_custom_field_new: New custom field - label_enumerations: Enumerations - label_enumeration_new: New value - label_information: Information - label_information_plural: Information - label_please_login: Please log in - label_register: Sign up - label_login_with_open_id_option: or login with OpenID - label_password_lost: Lost password - label_home: Home - label_my_page: My page - label_my_account: My account - label_my_message: My messages - label_my_projects: My projects - label_my_page_block: My page block - label_administration: Administration - label_login: Login - label_logout: Sign out - label_help: Help - label_reported_issues: Reported issues - label_assigned_to_me_issues: Issues assigned to me - label_last_login: Last connection - label_registered_on: Registered on - label_activity: Activities - label_overall_activity: Overall activity - label_user_activity: "%{value}'s activity" - label_new: New - label_new_user: registered a new account - label_logged_as: Logged in as - label_environment: Environment - label_authentication: Authentication - label_auth_source: Authentication mode - label_auth_source_new: New authentication mode - label_auth_source_plural: Authentication modes - label_subproject_plural: Subprojects - label_subproject_new: New subproject - label_and_its_subprojects: "%{value} and its subprojects" - label_min_max_length: Min - Max length - label_list: List - label_date: Date - label_integer: Integer - label_float: Float - label_boolean: Boolean - label_string: Text - label_text: Long text - label_attribute: Attribute - label_attribute_plural: Attributes - label_no_data: No data to display - label_change_status: Change status - label_history: History - label_attachment: Files - label_attachment_new: New file - label_attachment_delete: Delete file - label_attachment_plural: Files - label_file_added: File added - label_report: Report - label_report_plural: Reports - label_news: News - label_news_new: Add news - label_news_plural: News - label_news_latest: Latest news - label_news_view_all: View all news - label_news_added: News added - label_news_comment_added: Comment added to a news - label_settings: Settings - label_overview: Activities - label_version: Version - label_version_new: New version - label_version_plural: Versions - label_close_versions: Close completed versions - label_confirmation: Confirmation - label_export_to: 'Also available in:' - label_read: Read... - label_public_projects: Public projects - label_open_issues: open - label_open_issues_plural: open - label_closed_issues: closed - label_closed_issues_plural: closed - label_x_open_issues_abbr_on_total: - zero: 0 open / %{total} - one: 1 open / %{total} - other: "%{count} open / %{total}" - label_x_open_issues_abbr: - zero: 0 open - one: 1 open - other: "%{count} open" - label_x_closed_issues_abbr: - zero: 0 closed - one: 1 closed - other: "%{count} closed" - label_x_issues: - zero: 0 issues - one: 1 issue - other: "%{count} issues" - label_total: Total - label_total_time: Total time - label_permissions: Permissions - label_current_status: Current status - label_new_statuses_allowed: New statuses allowed - label_all: all - label_any: any - label_none: none - label_nobody: nobody - label_next: Next - label_previous: Previous - label_used_by: Used by - label_details: Details - label_add_note: Add a note - label_per_page: Per page - label_calendar: Calendar - label_months_from: months from - label_gantt: Gantt - label_internal: Internal - label_last_changes: "last %{count} changes" - label_change_view_all: View all changes - label_personalize_page: Personalize this page - label_comment: Comment - label_comment_plural: Comments - label_x_comments: - zero: no comments - one: 1 comment - other: "%{count} comments" - label_comment_add: Add a comment - label_comment_added: Comment added - label_comment_delete: Delete comments - label_query: Custom query - label_query_plural: Custom queries - label_query_new: New query - label_my_queries: My custom queries - label_filter_add: Add filter - label_filter_plural: Query condition - label_equals: is - label_not_equals: is not - label_in_less_than: in less than - label_in_more_than: in more than - label_in_the_next_days: in the next - label_in_the_past_days: in the past - label_in_users: 'in the user ' - label_greater_or_equal: '>=' - label_less_or_equal: '<=' - label_between: between - label_in: in - label_today: today - label_all_time: all time - label_yesterday: yesterday - label_this_week: this week - label_last_week: last week - label_last_n_weeks: "last %{count} weeks" - label_last_n_days: "last %{count} days" - label_this_month: this month - label_last_month: last month - label_this_year: this year - label_date_range: Date range - label_less_than_ago: less than days ago - label_more_than_ago: more than days ago - label_ago: days ago - label_contains: contains - label_not_contains: doesn't contain - label_any_issues_in_project: any issues in project - label_any_issues_not_in_project: any issues not in project - label_no_issues_in_project: no issues in project - label_day_plural: days - label_repository: Repository - #add by tan - label_repository_new: Repository setting - label_repository_no: Have no repository? - label_repository_new_repos: New repository - #end - label_repository_plural: Repositories - label_browse: Browse - label_branch: Branch - label_tag: Tag - label_revision: Revision - label_revision_plural: Revisions - label_revision_id: "Revision %{value}" - label_associated_revisions: Associated revisions - label_added: added - label_modified: modified - label_copied: copied - label_renamed: renamed - label_deleted: deleted - label_latest_revision: Latest revision - label_latest_revision_plural: Latest revisions - label_view_revisions: View revisions - label_view_all_revisions: View all revisions - label_max_size: Maximum size - label_sort_highest: Move to top - label_sort_higher: Move up - label_sort_lower: Move down - label_sort_lowest: Move to bottom - label_roadmap: Roadmap - label_roadmap_due_in: "Due in %{value}" - label_roadmap_overdue: "%{value} late" - label_roadmap_no_issues: No issues for this version - label_search: Search - label_result_plural: Results - label_all_words: All words - label_wiki: Wiki - label_wiki_edit: Wiki edit - label_wiki_edit_plural: Wiki edits - label_wiki_page: Wiki page - label_wiki_page_plural: Wiki pages - label_index_by_title: Index by title - label_index_by_date: Index by date - label_current_version: Current version - label_preview: Preview - label_feed_plural: Feeds - label_changes_details: Details of all changes - label_issue_tracking: Issue tracking - label_spent_time: Spent time - label_overall_spent_time: Overall spent time - label_f_hour: "%{value} hour" - label_f_hour_plural: "%{value} hours" - label_time_tracking: Time tracking - label_change_plural: Changes - label_statistics: Statistics - label_commits_per_month: Commits per month - label_commits_per_author: Commits per author - label_diff: diff - label_view_diff: View differences - label_diff_inline: inline - label_diff_side_by_side: side by side - label_options: Options - label_copy_workflow_from: Copy workflow from - label_permissions_report: Permissions report - label_watched_issues: Watched issues - label_related_issues: Related issues - label_applied_status: Applied status - label_loading: Loading... - label_relation_new: New relation - label_relation_delete: Delete relation - label_relates_to: Related to - label_duplicates: Duplicates - label_duplicated_by: Duplicated by - label_blocks: Blocks - label_blocked_by: Blocked by - label_precedes: Precedes - label_follows: Follows - label_copied_to: Copied to - label_copied_from: Copied from - label_end_to_start: end to start - label_end_to_end: end to end - label_start_to_start: start to start - label_start_to_end: start to end - label_stay_logged_in: Stay logged in - label_disabled: disabled - label_show_completed_versions: Show completed versions - label_me: me - label_board: Forums - label_board_description: Bring together the wisdom of crowds, and solve problems for you! - label_board_new: New forum - label_board_plural: Forums - label_board_locked: Locked - label_board_sticky: Sticky - label_topic_plural: Topics - field_sticky: '' - field_locked: '' - field_lock: '' - label_message_plural: Messages - label_message_last: Last message - label_message_new: New message - label_message_posted: Message added - label_reply_plural: Replies - label_send_information: Send account information to the user - label_year: Year - label_month: Month - label_week: Week - label_date_from: From - label_date_to: To - label_language_based: Based on user's language - label_sort_by: "Sort by %{value}" - label_send_test_email: Send a test email - label_feeds_access_key: RSS access key - label_missing_feeds_access_key: Missing a RSS access key - label_feeds_access_key_created_on: "RSS access key created %{value} ago" - label_module_plural: Modules - label_added_time_by: "Added by %{author} %{age} ago" - 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_changeset_plural: Changesets - label_default_columns: Default columns - label_no_change_option: (No change) - label_bulk_edit_selected_issues: Bulk edit selected issues - label_bulk_edit_selected_time_entries: Bulk edit selected time entries - label_theme: Theme - label_default: Default - label_search_titles_only: Search titles only - label_user_mail_option_all: "For any event on all my projects" - label_user_mail_option_selected: "For any event on the selected projects only..." - label_user_mail_option_none: "No events" - label_user_mail_option_only_my_events: "Only for things I watch or I'm involved in" - label_user_mail_option_only_assigned: "Only for things I am assigned to" - label_user_mail_option_only_owner: "Only for things I am the owner of" - label_user_mail_no_self_notified: "I don't want to be notified of changes that I make myself" - label_registration_activation_by_email: account activation by email - label_registration_manual_activation: manual account activation - label_registration_automatic_activation: automatic account activation - label_display_per_page: "Per page: %{value}" - label_age: Age - label_change_properties: Change properties - label_general: General - label_more: More - label_scm: SCM - label_plugins: Plugins - label_ldap_authentication: LDAP authentication - label_downloads_abbr: D/L - label_optional_description: Optional description - label_add_another_file: Add another file - label_preferences: Preferences - label_chronological_order: In chronological order - label_reverse_chronological_order: In reverse chronological order - label_planning: Planning - label_incoming_emails: Incoming emails - label_generate_key: Generate a key - label_issue_watchers: Watchers - label_example: Example - label_display: Display - label_sort: Sort - label_ascending: Ascending - label_descending: Descending - label_date_from_to: From %{start} to %{end} - label_wiki_content_added: Wiki page added - label_wiki_content_updated: Wiki page updated - label_group: Group - label_group_plural: Groups - label_group_new: New group - label_time_entry_plural: Spent time - label_version_sharing_none: Not shared - label_version_sharing_descendants: With subprojects - label_version_sharing_hierarchy: With project hierarchy - label_version_sharing_tree: With project tree - label_version_sharing_system: With all projects - label_update_issue_done_ratios: Update issue done ratios - label_copy_source: Source - label_copy_target: Target - label_copy_same_as_target: Same as target - label_display_used_statuses_only: Only display statuses that are used by this tracker - label_api_access_key: API access key - label_missing_api_access_key: Missing an API access key - label_api_access_key_created_on: "API access key created %{value} ago" - 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_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 - label_issues_visibility_all: All issues - label_issues_visibility_public: All non private issues - label_issues_visibility_own: Issues created by or assigned to the user - label_git_report_last_commit: Report last commit for files and directories - label_parent_revision: Parent - label_child_revision: Child - label_export_options: "%{export_format} export options" - label_copy_attachments: Copy attachments - label_copy_subtasks: Copy subtasks - label_item_position: "%{position} of %{count}" - label_completed_versions: Completed versions - label_search_for_watchers: Search for watchers to add - label_session_expiration: Session expiration - label_show_closed_projects: View closed projects - label_status_transitions: Status transitions - label_fields_permissions: Fields permissions - label_readonly: Read-only - label_required: Required - label_attribute_of_project: "Project's %{name}" - label_attribute_of_issue: "Issue's %{name}" - label_attribute_of_author: "Author's %{name}" - label_attribute_of_assigned_to: "Assignee's %{name}" - label_attribute_of_user: "User's %{name}" - label_attribute_of_fixed_version: "Target version's %{name}" - label_cross_project_descendants: With subprojects - label_cross_project_tree: With project tree - label_cross_project_hierarchy: With project hierarchy - label_cross_project_system: With all projects - label_gantt_progress_line: Progress line - - button_login: Login - button_submit: Submit - button_save: Save - button_check_all: Check all - button_uncheck_all: Uncheck all - button_collapse_all: Collapse all - button_expand_all: Expand all - button_delete: Delete - button_create: Create - button_create_and_continue: Create and continue - button_test: Test - button_edit: Edit - button_edit_associated_wikipage: "Edit associated Wiki page: %{page_title}" - button_add: Add - button_change: Change - button_apply: Query - button_clear: Cancel query - button_lock: Lock - button_unlock: Unlock - button_download: Download - button_list: List - button_view: View - button_move: Move - button_move_and_follow: Move and follow - button_back: Back - button_cancel: Cancel - button_activate: Activate - button_sort: Sort - button_log_time: Log time - button_rollback: Rollback to this version - button_watch: Watch - button_unwatch: Unwatch - button_reply: Reply - button_archive: Archive - button_unarchive: Unarchive - button_reset: Reset - button_rename: Rename - button_change_password: Change password - button_copy: Copy - button_copy_and_follow: Copy and follow - button_annotate: Annotate - button_update: Update - button_configure: Configure - button_quote: Quote - button_duplicate: Duplicate - button_show: Show - button_hide: Hide - button_edit_section: Edit this section - button_export: Export - button_delete_my_account: Delete my account - button_close: Close - button_reopen: Reopen - - status_active: active - status_registered: registered - status_locked: locked - - project_status_active: active - project_status_closed: closed - project_status_archived: archived - - version_status_open: open - version_status_locked: locked - version_status_closed: closed - - field_active: Active - - text_select_mail_notifications: Select actions for which email notifications should be sent. - text_regexp_info: eg. ^[A-Z0-9]+$ - text_min_max_length_info: 0 means no restriction - text_project_destroy_confirmation: Are you sure you want to delete this project and related data? - text_subprojects_destroy_warning: "Its subproject(s): %{value} will be also deleted." - text_workflow_edit: Select a role and a tracker to edit the workflow - text_are_you_sure: Are you sure? - text_journal_changed: "%{label} changed from %{old} to %{new}" - text_journal_changed_no_detail: "%{label} updated" - text_journal_set_to: "%{label} set to %{value}" - text_journal_deleted: "%{label} deleted (%{old})" - text_journal_added: "%{label} %{value} added" - text_tip_issue_begin_day: issue beginning this day - text_tip_issue_end_day: issue ending this day - text_tip_issue_begin_end_day: issue beginning and ending this day - text_project_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed, must start with a lower case letter.Once saved, the identifier cannot be changed.' - 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_tracker_no_workflow: No workflow defined for this tracker - text_unallowed_characters: Unallowed characters - text_comma_separated: Multiple values allowed (comma separated). - text_line_separated: Multiple values allowed (one line for each value). - text_issues_ref_in_commit_messages: Referencing and fixing issues in commit messages - text_issue_added: "Issue %{id} has been reported by %{author}." - text_issue_updated: "Issue %{id} has been updated by %{author}." - text_wiki_destroy_confirmation: Are you sure you want to delete this wiki and all its content? - text_issue_category_destroy_question: "Some issues (%{count}) are assigned to this category. What do you want to do?" - text_issue_category_destroy_assignments: Remove category assignments - text_issue_category_reassign_to: Reassign issues to this category - text_user_mail_option: "For unselected projects, you will only receive notifications about things you watch or you're involved in (eg. issues you're the author or assignee)." - text_no_configuration_data: "Roles, trackers, issue statuses and workflow have not been configured yet.\nIt is highly recommended to load the default configuration. You will be able to modify it once loaded." - text_load_default_configuration: Load the default configuration - text_status_changed_by_changeset: "Applied in changeset %{value}." - text_time_logged_by_changeset: "Applied in changeset %{value}." - text_issues_destroy_confirmation: 'Are you sure you want to delete the selected issue(s)?' - text_issues_destroy_descendants_confirmation: "This will also delete %{count} subtask(s)." - text_time_entries_destroy_confirmation: 'Are you sure you want to delete the selected time entr(y/ies)?' - text_select_project_modules: 'Select modules to enable for this project:' - text_default_administrator_account_changed: Default administrator account changed - text_file_repository_writable: Attachments directory writable - text_plugin_assets_writable: Plugin assets directory writable - text_rmagick_available: RMagick available (optional) - text_destroy_time_entries_question: "%{hours} hours were reported on the issues you are about to delete. What do you want to do?" - text_destroy_time_entries: Delete reported hours - text_assign_time_entries_to_project: Assign reported hours to the project - text_reassign_time_entries: 'Reassign reported hours to this issue:' - text_user_wrote: "%{value} wrote:" - text_enumeration_destroy_question: "%{count} objects are assigned to this value." - text_enumeration_category_reassign_to: 'Reassign them to this value:' - text_email_delivery_not_configured: "Email delivery is not configured, and notifications are disabled.\nConfigure your SMTP server in config/configuration.yml and restart the application to enable them." - text_repository_usernames_mapping: "Select or update the Trustie user mapped to each username found in the repository log.\nUsers with the same Trustie and repository username or email are automatically mapped." - text_diff_truncated: '... This diff was truncated because it exceeds the maximum size that can be displayed.' - text_custom_field_possible_values_info: 'One line for each value' - text_wiki_page_destroy_question: "This page has %{descendants} child page(s) and descendant(s). What do you want to do?" - text_wiki_page_nullify_children: "Keep child pages as root pages" - 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_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_scm_path_encoding_note: "Default: UTF-8" - text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo) - text_mercurial_repository_note: Local repository (e.g. /hgrepo, c:\hgrepo) - text_scm_command: Command - text_scm_command_version: Version - 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. - text_issue_conflict_resolution_overwrite: "Apply my changes anyway (previous notes will be kept but some changes may be overwritten)" - text_issue_conflict_resolution_add_notes: "Add my notes and discard my other changes" - text_issue_conflict_resolution_cancel: "Discard all my changes and redisplay %{link}" - text_account_destroy_confirmation: "Are you sure you want to proceed?\nYour account will be permanently deleted, with no way to reactivate it." - text_session_expiration_settings: "Warning: changing these settings may expire the current sessions including yours." - text_project_closed: This project is closed and read-only. - text_turning_multiple_off: "If you disable multiple values, multiple values will be removed in order to preserve only one value per item." - - default_role_manager: Manager - default_role_developer: Developer - default_role_reporter: Reporter - default_tracker_bug: Bug - default_tracker_feature: Feature - default_tracker_support: Support - default_issue_status_new: New - default_issue_status_in_progress: In Progress - default_issue_status_resolved: Resolved - default_issue_status_feedback: Feedback - default_issue_status_closed: Closed - default_issue_status_rejected: Rejected - default_doc_category_user: User documentation - default_doc_category_tech: Technical documentation - default_priority_low: Low - default_priority_normal: Normal - default_priority_high: High - default_priority_urgent: Urgent - default_priority_immediate: Immediate - default_activity_design: Design - default_activity_development: Development - - enumeration_issue_priorities: Issue priorities - enumeration_doc_categories: Document categories - enumeration_activities: Activities - enumeration_system_activity: System Activity - description_filter: Filter - description_search: Searchfield - description_choose_project: Projects - description_project_scope: Search scope - description_notes: Notes - description_message_content: Message content - description_query_sort_criteria_attribute: Sort attribute - description_query_sort_criteria_direction: Sort direction - description_user_mail_notification: Mail notification settings - description_available_columns: Available Columns - description_selected_columns: Selected Columns - description_all_columns: All Columns - description_issue_category_reassign: Choose issue category - description_wiki_subpages_reassign: Choose new parent page - description_date_range_list: Choose range from list - description_date_range_interval: Choose range by selecting start and end date - description_date_from: Enter start date - description_date_to: Enter end date - text_repository_identifier_info: 'Only lower case letters (a-z), numbers, dashes and underscores are allowed.
Once saved, the identifier cannot be changed.' - - #modify by mkz - #by young - label_requirement: Calls - label_requirement_focus: Calls # modified by bai - label_developer: Users - label_investor: Investor: - label_theme: Theme - label_logged_as_new: Current user - button_register: Register - issue_list: Issue list - lastest_respond: Lastest reply - label_news_lastest: Lastest news - label_version_display_settings: Display settings - label_versions_progress: Complete schedule - label_versions_description: Versions description - label_my_photo: My photo - label_documents_sort: Order setting: - label_activities_settings: Display settings - #end - - label_joined_course: Joined Courses - label_created_course: Created Courses - - #huang - label_file_new: Download - label_user_edit: "Edit information" - label_user_info: "User information" #huang 添加 - label_user_watcher: "Following" # huang添加的 # modified by bai - label_user_fans: "Followed by" # modified by bai - - # modify by men - label_x_user_fans: - zero: fan - one: fan - other: fans - #end - label_user_commits: "Code commits" - label_user_watchered: "Followed by" # huang添加的 - label_user_newfeedback: "Messages" ## huang添加的 # modified by bai - label_user_login: "Last login:" - label_user_mail: "E-mail:" - label_user_joinin: "Join date:" - label_user_activities: "You have no activities,come and join us!" - label_user_activities_other: The user has no activities now! - label_project_overview: "Overview" - label_project_tool: "Tool" - label_project_issues: "Issues" - label_project_newother: "See other comments" - label_project_newshare: "has shared" - label_project_newadd: "added" - label_project_unadd: "No project,go to creat it!" - label_project_un: "You haven't joined any project!" - #end by huang - - #added by liuping - button_unfollow: Unfollow - button_follow: Follow - label_delete_confirm: Confirm delete? - label_more_tags: More - label_tags_bid: Call name - label_tags_bid_description: call description - label_tags_issue_description: issue description - label_tags_all_objects: all objects - label_apply_project: Apply Project - label_apply_project_waiting: "Application has been submitted, please wait for administrator review." - label_unapply_project: Unsubscribe - - #fq - button_leave_meassge: Submit - label_leave_message_to: leave %{name} a message - label_leave_message: Message content - label_message: message board - field_add: Add before %{time} - button_more: More - label_user_response: Feedbacks # modified by bai - label_bidding_project: projects - button_bidding: I will participate in it - label_new_call: New call - label_user_information: My informations - - #Customer added!Added by nie - label_create_time: Created time - label_current_contributors: current contributors - #modify by men - label_x_current_contributors: - zero: current contributor - one: current contributor - other: current contributors - #end - label_lines_of_code: lines of code - label_since_last_commits: since last commit - label_users_on_trustie: User - label_front: first page - label_commit_on: commit times - #modify by men - label_x_commit_on: - zero: commit time - one: commit time - other: commit times - #end - label_follow_people: following # modified by bai - #modify by men - label_x_follow_people: - zero: follower - one: follower - other: followers - #end - label_member_since: joined - label_contribute_to: Participates %{project_count} projects: - #modify by men - label_x_contribute_to: - zero: Participates %{count} project: - one: Participates %{count} project: - other: Participates %{count} projects: - #end - label_total_commit: Totally %{total_commit} commits # modified by bai - #modify by men - label_x_total_commit: - zero: Totally %{count} commit - one: Totally %{count} commit - other: Totally %{count} commits - #end - label_upload_profile: Upload avatar - label_type_as: Type as - label_status_as: Status as - label_priority_as: Priority as - label_member_list: Member list - label_author_name: Posted by %{author_name} - label_comments_count: (%{count} comments) - label_post_on: posts on - label_find_all_comments: view all comments - label_updated_time_on: " Updated on %{value} " - label_call_list: Calls list - - label_requirement_list: Requirement list - label_x_biding_project: #modify by men - zero: project - one: project - other: projects - #end - label_x_responses: #modify by men - zero: comment - one: comment - other: comments - #end - label_x_followers: #modified by men - zero: follower - one: follower - other: followers - #end - - - - label_price: price: - label_RMB_sign: ¥ - label_investment_budget: Investment budget: - label_investment_time_limit: Investment time limit: - label_my_respond: Feedbacks: # modified by bai - label_respond_requirement: has commented this call - label_deadline: deadline yyyy-mm-dd - label_requirement_name: give your requirement a name ~~ - label_requirement_description: content:descript your requirement - label_requirement_bargain_money: type in your rewards(ex. money, reward, grade) - label_wrong_budget: The error format of money - label_wrong_date: wrong date format, input right date yyyy-mm-dd - button_upload_photo: Upload photo - label_leave_me_message: left a message to me - label_leave_others_message: leave message to him/her - label_leave_a_message: Leave him/her a message: - label_leave_your_message: Leave a message to you - label_new_activities: ' has new activity in' # modified by bai - label_new_activity: ' has new activity in' - label_i_new_activity: ' have new activity in' - label_create_project: had participated in - label_praise: praise - label_cancel_praise: cancel praise - label_bid_reason: Please show your reason - default_tracker_task: Task - label_create_new_projects_description: Create a new project, you will open a magical journey of collaborative creation and development! - label_call_for_bids_description: Publish your call for anything, feel the excitement of hundreds respond to a single call! - label_create_course_description: Create a new course, let us share the public resources in the course community which are more than you can imagine! - label_news: News - label_news_description: Track the latest activities of projects, and obtain the latest information! - label_milestone: Milestone - label_milestone_description: Review the commits, branches and versions of your project! - label_features: Features - label_has_praisers: praisers(%{count}) - label_has_watchers: following(%{count}) # modified by bai - label_has_fans: followed by(%{count}) # modified by bai - #modify by men - label_x_has_fans: - zero: fan(%{count}) - one: fan(%{count}) - other: fans(%{count}) - #end - label_me: me - label_my: my - label_i: I - label_join_bidding: joined the bidding - label_bidding_user: Bidding user: - label_bidding_reason: Bidding reason: - label_username: username: - label_password: password: - label_about_requirement: about requirement: - label_about_issue: about issue: - label_quote_my_words: ' quoted my words' - label_have_respond: had a respond - label_welcome: Welcome - - label_goto: Go to>> - label_join: join Trustie! - label_repository_new: link to existing SVN repository - label_repository_path: path of repository - label_repository_new_repos: create a new repository - label_repository_no: have no repository? - label_welcome_page_to: Participate %{project_count} projects! - label_repository_path_not_null: repository path can't be null - label_password_not_null: password can't be blank - label_exist_repository_path: Define exist repository's path of URL and format must be file:///, http://, https://, svn:// - label_project_no_activity: The project has no activities now! - label_follow_no_requirement: You don't have followed any requirements! - label_no_user_respond_you: There is no respond for you! - label_tags_issue: issue: - label_tags_project_name: Project name: - label_tags_project_description: Project description: - label_tags_user_mail: User E-mail: - label_tags_user_name: User Name: - label_tags_numbers: Tag numbers: - label_max_number: Must be at most 25 characters long. - label_all_revisions: All revisions: - label_repository_name: Repository name - label_upassword_info: The password can be shared in the group - label_how_commit_code: How to commit code: - label_how_commit_code_chinese: Chinese - label_welcome_leave_message: Hi!The platform is currently in beta version.If you have any comments and suggestions, please - label_welcome_click_me: Click me - label_issue_praise: Good question,praise! - label_issue_tread: Poor question,tread! - label_issue_praise_over: Praised over! - label_issue_tread_over: Treaded over! - label_issue_appraise_over: Appraised over! - label_welcome_my_respond: Please leave your comments and suggestions here! - label_no_current_fans: the user has no fans now - label_no_current_watchers: the user hasn't watched others - label_project_tool_response: Response - label_course_feedback: Feedback - label_tags_search_result: Search Results - label_active_call: call - label_tags_call: Calls - label_user_extensions: Other information - label_boy: Man - label_girl: Woman - field_gender: Gender - field_birthday: Birthday - field_brief_introduction: Info - field_location: Location - field_occupation: Position - field_work_experience: Work experience(year) - field_zip_code: Zip code - label_reward: reward: - label_credit: credit: - label_choose_reward: choose reward - label_money: money - label_reward_1: others - label_bids_credit: credit - label_bids_credit_number: points - field_budget: reward - field_deadline: deadline - label_tags_selected: Selected Tags - label_tags_related: Related Tags - button_project_tags_add: Add - label_issue_query_condition: Query condition - label_homework_source: Task - label_issue_query: Query - label_issue_cancel_query: Cancel query - field_reward_type: The type of reward - label_tags_no: no tags now! - label_bid_publish: published - label_bid_project: projects - label_project_no_follow: The project hasn't been followed now! - label_no_bid_project: has no participate project - label_bids_reward_method: reward: - label_bids_reward_what: input what for reward - label_call_bonus: bonus - label_bids_form_new_description: Publish a requirement,a competition or a course work. - label_bids_new_money: input the award money,such as 500,2.5 etc. - label_bids_new_credit: input the work corresponding course credits,such as 3,2.5 etc. - label_bids_new_content: input the award content,such as certificate,things etc. - label_user_login_tips: You havn't logged in,for leaving message please login first - label_user_login_new: login - label_project_sort: the way of sorting - #modified by bai - label_sort_by_time: sorted by time - label_sort_by_active: sorted by active - label_sort_by_influence: sorted by influence - #end - label_bids_published: published - label_bids_published_ago: ago - label_welcome_trustie: Trustie forge - label_welcome_trustie_project: Online projects hosting platform - label_welcome_trustie_course: Online Courses practice platform - label_welcome_trustie_project_description: Software for Chinese college students and practitioners to provide social-oriented project management, code hosting, resource sharing, cooperation and exchange. - label_welcome_trustie_course_description: Teachers and Students for Chinese universities to provide social-oriented curriculum management, resource sharing, cooperation achieved, collaborative research. - label_welcome_trustie_description: a socialized collaboration platform for project management, collaborative research, software development and software crowdsourcing for creative university students and entrepreneurs. - label_user_project: Projects - label_bid_respond_quote: Respond - label_bid_if_agreement: If you like me, please press me #bai - label_bid_respond_delete: Delete - label_newfeedback_message: messages - label_newfeedback_quote: Respond - label_newfeedback_delete: Delete - label_user_all_activity: All activities - label_user_activity_myself: About me - label_user_all_respond: All replies - label_layouts_feedback: Messages - label_have_feedback: Have - label_of_feedback: Of - label_welcome_participate: participates - #modify by men - label_x_welcome_participate: - zero: participate - one: participate - other: participates - #end - label_welcome_participate_project: projects - label_projects_feedback: responded to the project - label_projects_feedback_respond: Respond - label_projects_feedback_respond_success: Respond success - button_projects_feedback_respond: Respond - label_projects_feedback_respond_content: Please input your words - label_in_issues: in the issue: - label_in_bids: in the call: - label_in_users: in the user: - label_user_create_project: has created - -#added by bai - label_identity: Identity - label_teacher: Teacher - label_student: Student - label_school_all: Schools - label_other: Other - label_gender: Gender - label_gender_male: male - label_gender_female: female - label_location: Location -#end - label_course: Course - label_course_new: New course - label_public_info: "If you don't choose public, only the project's members can see the project." - label_course_student: Student - label_homework: Task - label_course_new_homework: New homework - label_course_homework_list: Homework List - label_course_homework_new: new homework - - label_x_course_data: - zero: File - one: File - other: Files - - label_x_base_courses_student: - zero: student - one: students - other: students - label_x_base_courses_teacher: - zero: teacher - one: teachers - other: teachers - #add by men - label_brief_introduction: Personality words - label_technical_title: Title - label_technicl_title_professor: Professor - label_technicl_title_associate_professor: Associate professor - label_technicl_title_lecturer: Lecturer - label_technicl_title_teaching_assistant: Teaching assistant - label_account_identity_teacher: Teacher - label_account_identity_student: Student - label_account_identity_developer: Developer - label_account_identity_enterprise: Enterprise - label_account_identity_choose: --Please choose your identity-- - label_enter_college: College Entrance - lable_enter_enterprise: Enterprise Entrance - label_homework_info: Status - label_question_student: Feedback - label_student_response: Feedback - label_my_question: Please raise your questions here! - label_teacher_homework: "Teacher's name" - label_course_homework: Corresponding courses - label_course_done: finished courses - label_course_doing: Doing course - label_limit_time: Deadline - label_commit_homework: Submitted Task - label_no_course_project: No submitted work! - button_clear_requirement: Cancel -#end - label_x_bids_responses: #modify by huang - zero: response - one: response - other: responses - #end - label_teaching_course: My Courses - label_release_homework: Released Tasks - label_term: Term - label_spring: spring term - label_summer: summer term - label_autumn: autumn term - label_winter: winter term - text_command: The password is required when applying a course, and it will be released by the teacher of. - label_enterprise_into: Enterprise Entrance - label_college_into: College Entrance - label_user_course: Courses - label_new_course: Courses - field_tea_name: Teacher - label_course_college: College - label_x_task: - zero: Task - one: Task - other: Tasks - label_project_course_unadd: You have no course,creat one now! - label_my_create_honework_no_homework: no task now! - label_my_homework_no_homework: no task now! - label_x_member: - zero: member - one: member - other: members - label_x_data: - zero: file - one: file - other: files - label_bid_show_course_name: Course - label_bid_show_teacher_name: Teacher - label_bid_contest_show_course_name: Course - label_bid_contest_show_teacher_name: Teacher - label_x_homework_project: - zero: submitted task - one: submitted task - other: submitted tasks - label_new_homework: Tasks - label_new_contest: Contests - label_contest_list: Contests list - label_newtype_contest: Release contest - label_question_requirement: introduce a question! - label_contest_requirement: has commented this contest - button_bidding_homework: To take part in contest - label_bids_form_contest_new_description: Enterprise or college can release a contest here. - label_contest_name: Input the name of the contest - label_contest_description: Content:description your contest - label_main_teacher: Main teacher - label_main_term: Term - label_teacher_work_unit: Position - label_course_overview: Status - label_course_file: File - label_stores_index: Resource search - label_course_news: News - - label_x_base_courses_member: - zero: member - one: member - other: members - - label_bids_task_list: Tasks list - label_join_course: join course - label_exit_course: exit course - label_new_join: Join - label_new_join_order: Please input the course order. - label_homeworks_form_new_description: Release a task,the submit form of the task may be accessory or project,setting in the task form. - label_course_settings: Setting - field_homework_type: Submit form - label_task_submit_form_accessory: Submitted as accessory - label_task_submit_form_project: Submitted as project - label_news_notice: Release course news - - role_of_course: Role - label_student: student - label_teacher: teacher - label_ta: teacher assistant - label_in_course: in course - label_assign_homework: assigned homewok - label_noawards: No awards - label_user_location: Location - label_requirement_enterprise: Requirements - label_requirement_enterprise_list: Requirements List - label_contest_innovate: Competitions - label_software_user: Users - label_course_practice: Courses - label_course_all: Teacher - label_teacher_all: Student - label_user_home: User Space - - field_hidden_repo: code protected - label_newbie_faq: newbie FAQ - label_hot_project: 'HOT Projects' - label_memo_create_succ: Memo was successfully created. - label_memo_create_fail: Memo was failures created. - label_forum_create_succ: Forum was successfully created. - label_forum_create_fail: Forum was failures created. - label_forum_edit: Editing forum - label_memo_create: publish - label_memo_new: new memo - label_memo_edit: edit memo - label_project_module_forums: Forums - label_forum: Forum - label_tags_forum_description: Forum description - label_tags_forum: Call forum - label_memo_locked: 'Topic is locked' - label_downloads_list: enter file list. - label_sumbit_empty: search bar need container. - label_setup_time: Start date - label_endup_time: Over date - label_class_period: Class hour - label_class_hour: period - label_activity_time: publish date - - - # ajax异步验证 - modal_valid_passing: can be used. diff --git a/trustie2/config/locales/zh.yml b/trustie2/config/locales/zh.yml deleted file mode 100644 index e071f2b71..000000000 --- a/trustie2/config/locales/zh.yml +++ /dev/null @@ -1,2008 +0,0 @@ - -# Chinese (China) translations for Ruby on Rails -# by tsechingho (http://github.com/tsechingho) -zh: - # Text direction: Left-to-Right (ltr) or Right-to-Left (rtl) - direction: ltr - jquery: - locale: "zh-CN" - date: - formats: - # Use the strftime parameters for formats. - # When no format has been given, it uses default. - # You can provide other formats here if you like! - default: "%Y-%m-%d" - short: "%b%d日" - long: "%Y年%b%d日" - zh_date: - formats: - default: "%Y年%m月%d日" - - day_names: [星期天, 星期一, 星期二, 星期三, 星期四, 星期五, 星期六] - abbr_day_names: [日, 一, 二, 三, 四, 五, 六] - - # Don't forget the nil at the beginning; there's no such thing as a 0th month - month_names: [~, 一月, 二月, 三月, 四月, 五月, 六月, 七月, 八月, 九月, 十月, 十一月, 十二月] - abbr_month_names: [~, 1月, 2月, 3月, 4月, 5月, 6月, 7月, 8月, 9月, 10月, 11月, 12月] - # Used in date_select and datime_select. - order: - - :year - - :month - - :day - - time: - formats: - default: "%Y年%b%d日 %A %H:%M:%S" - time: "%H:%M" - short: "%b%d日 %H:%M" - long: "%Y年%b%d日 %H:%M" - am: "上午" - pm: "下午" - - datetime: - distance_in_words: - half_a_minute: "半分钟" - less_than_x_seconds: - one: "1秒内" - other: "少于 %{count} 秒" - x_seconds: - one: "1秒" - other: "%{count} 秒" - less_than_x_minutes: - one: "1分钟内" - other: "少于 %{count} 分钟" - x_minutes: - one: "1分钟" - other: "%{count} 分钟" - about_x_hours: - one: "大约1小时" - other: "大约 %{count} 小时" - x_hours: - one: "1 小时" - other: "%{count} 小时" - x_days: - one: "1天" - other: "%{count} 天" - about_x_months: - one: "大约1个月" - other: "大约 %{count} 个月" - x_months: - one: "1个月" - other: "%{count} 个月" - about_x_years: - one: "大约1年" - other: "大约 %{count} 年" - over_x_years: - one: "超过1年" - other: "超过 %{count} 年" - almost_x_years: - one: "将近 1 年" - other: "将近 %{count} 年" - - number: - # Default format for numbers - format: - separator: "." - delimiter: "" - precision: 3 - human: - format: - delimiter: "" - precision: 3 - storage_units: - format: "%n %u" - units: - byte: - one: "Byte" - other: "Bytes" - kb: "KB" - mb: "MB" - gb: "GB" - tb: "TB" - -# Used in array.to_sentence. - support: - array: - sentence_connector: "和" - skip_last_comma: false - - activerecord: - errors: - template: - header: - one: "由于发生了一个错误 %{model} 无法保存" - other: "%{count} 个错误使得 %{model} 无法保存" - messages: - inclusion: "不包含于列表中" - exclusion: "是保留关键字" - invalid: "是无效的" - confirmation: "与确认值不匹配" - accepted: "必须是可被接受的" - empty: "不能留空" - blank: "不能为空字符" - too_long: "过长(最长为 %{count} 个字符)" - too_short: "过短(最短为 %{count} 个字符)" - wrong_length: "长度非法(必须为 %{count} 个字符)" - taken: "已经被使用" - not_a_number: "不是数字" - not_a_date: "不是合法日期" - greater_than: "必须大于 %{count}" - greater_than_or_equal_to: "必须大于或等于 %{count}" - equal_to: "必须等于 %{count}" - less_than: "必须小于 %{count}" - less_than_or_equal_to: "必须小于或等于 %{count}" - odd: "必须为单数" - even: "必须为双数" - greater_than_start_date: "必须在起始日期之后" - not_same_project: "不属于同一个项目" - circular_dependency: "此关联将导致循环依赖" - cant_link_an_issue_with_a_descendant: "问题不能关联到它的子任务" - - actionview_instancetag_blank_option: 请选择 - - attachment_all: "全部" - attachment_sufix_browse: "文件类型" - attachment_browse: "内容类型" - attachment_type: '分类' - general_text_No: '否' - general_text_Yes: '是' - general_text_no: '否' - general_text_yes: '是' - general_lang_name: 'Simplified Chinese (简体中文)' - general_csv_separator: ',' - general_csv_decimal_separator: '.' - general_csv_encoding: gb18030 - general_pdf_encoding: gb18030 - general_first_day_of_week: '7' - - label_approve: 批准 - label_refusal: 拒绝 - - notice_account_updated: 帐号更新成功 - notice_account_invalid_creditentials: 无效的用户名或密码 - notice_account_invalid_creditentials_new: 您还未到邮箱激活 - notice_account_password_updated: 密码更新成功 - notice_account_wrong_password: 密码错误 - notice_account_register_done: 帐号创建成功,请使用注册确认邮件中的链接来激活您的帐号。 - notice_account_unknown_email: 未知用户 - notice_can_t_change_password: 该帐号使用了外部认证,因此无法更改密码。 - notice_account_lost_email_sent: 系统已将引导您设置新密码的邮件发送给您。 - notice_account_activated: 您的帐号已被激活。 - notice_successful_create: 创建成功 - notice_successful_update: 更新成功 - notice_successful_delete: 删除成功 - notice_failed_delete: 删除失败 - notice_successful_connection: 连接成功 - notice_file_not_found: 您访问的页面不存在或已被删除。 - notice_locking_conflict: 数据已被另一位用户更新 - notice_not_authorized: 对不起,您无权访问此页面。 - notice_not_contest_setting_authorized: 对不起,您无权配置此竞赛。 - notice_not_contest_delete_authorized: 对不起,您无权删除此竞赛。 - notice_not_authorized_archived_project: 要访问的项目已经归档。 - notice_email_sent: "邮件已发送至 %{value}" - notice_email_error: "发送邮件时发生错误 (%{value})" - notice_feeds_access_key_reseted: 您的RSS存取键已被重置。 - notice_api_access_key_reseted: 您的API访问键已被重置。 - notice_failed_to_save_issues: "%{count} 个问题保存失败(共选择 %{total} 个问题):%{ids}." - notice_failed_to_save_members: "成员保存失败: %{errors}." - notice_no_issue_selected: "未选择任何问题!请选择您要编辑的问题。" - notice_account_pending: "您的帐号已被成功创建,正在等待管理员的审核。" - notice_default_data_loaded: 成功载入默认设置。 - notice_unable_delete_version: 无法删除版本 - notice_unable_delete_time_entry: 无法删除工时 - notice_issue_done_ratios_updated: 问题完成度已更新。 - notice_gantt_chart_truncated: "这个表是截断的因为它超过了可以显示的最大数量(%{max})" - - error_complete_occupation: "请您填写工作单位,否则本系统的部分功能将无法正常使用。" - - error_can_t_load_default_data: "无法载入默认设置:%{value}" - error_scm_not_found: "版本库中不存在该条目和(或)其修订版本。" - error_scm_command_failed: "访问版本库时发生错误:%{value}" - error_scm_annotate: "该条目不存在或无法追溯。" - error_issue_not_found_in_project: '问题不存在或不属于此项目' - error_no_tracker_in_project: 该项目未设定跟踪标签,请检查项目配置。 - error_no_default_issue_status: 未设置默认的问题状态。请检查系统设置("管理" -> "问题状态")。 - error_can_not_delete_custom_field: 无法删除自定义属性 - error_can_not_delete_tracker: "该跟踪标签已包含问题,无法删除" - error_can_not_remove_role: "该角色正在使用中,无法删除" - error_can_not_reopen_issue_on_closed_version: 该问题被关联到一个已经关闭的版本,因此无法重新打开。 - error_can_not_archive_project: 该项目无法被存档 - error_issue_done_ratios_not_updated: 问题完成度未能被更新。 - error_workflow_copy_source: 请选择一个源跟踪标签或者角色 - error_workflow_copy_target: 请选择目标跟踪标签和角色 - error_unable_delete_issue_status: '无法删除问题状态' - error_unable_to_connect: "无法连接 (%{value})" - warning_attachments_not_saved: "%{count} 个文件保存失败" - - mail_title_lost_password: "您的 %{value} 密码" - mail_body_lost_password: '请点击以下链接来修改您的密码:' - mail_title_register: "%{value}帐号激活" - mail_body_register: '请点击以下链接来激活您的帐号:' - mail_body_account_information_external: "您可以使用您的 %{value} 帐号来登录。" - mail_body_account_information: 您的帐号信息 - mail_title_account_activation_request: "%{value}帐号激活请求" - mail_body_account_activation_request: "新用户(%{value})已完成注册,正在等候您的审核:" - mail_title_reminder: "%{count} 个问题需要尽快解决 (%{days})" - mail_body_reminder: "指派给您的 %{count} 个问题需要在 %{days} 天内完成:" - mail_title_wiki_content_added: "'%{id}' wiki页面已添加" - mail_body_wiki_content_added: "'%{id}' wiki页面已由 %{author} 添加。" - mail_title_wiki_content_updated: "'%{id}' wiki页面已更新。" - mail_body_wiki_content_updated: "'%{id}' wiki页面已由 %{author} 更新。" - - - - field_name: 名称 - #added by huang - field_tea_name: 教师 - field_couurse_time: 学时 - field_course_code: 学分 - field_state: 加入课程口令 - field_term: 课程学期 - field_course_un: 暂未填写 - #end - field_description: 描述 - field_summary: 摘要 - field_is_required: 必填 - field_firstname: 名字 - field_firstname_eg: '(例:张三丰,请填写[三丰])' - field_lastname: 姓氏 - field_lastname_eg: '(例:张三丰,请填写[张])' - field_mail: 邮件地址 - field_filename: 文件 - field_filesize: 大小 - field_downloads: 下载次数 - field_author: 作者 - field_created_on: 创建于 - field_updated_on: 更新于 - field_field_format: 格式 - field_is_for_all: 用于所有项目 - field_possible_values: 可能的值 - field_regexp: 正则表达式 - field_min_length: 最小长度 - field_max_length: 最大长度 - field_value: 值 - field_category: 类别 - field_title: 标题 - field_project: 项目 - field_issue: 问题 - field_status: 状态 - field_notes: 说明 - field_is_closed: 已关闭的问题 - field_is_default: 默认值 - field_tracker: 跟踪 - field_title: 主题 - field_due_date: 计划完成日期 - field_assigned_to: 指派给 - field_priority: 优先级 - field_fixed_version: 目标版本 - field_user: 用户 - field_principal: 用户/用户组 - field_role: 角色 - field_homepage: 主页 - field_time: 课时 - field_code: 学分 - field_is_public: 公开 - field_parent: 上级项目 - field_is_in_roadmap: 在路线图中显示 - field_login: 登录名 - field_mail_notification: 邮件通知 - field_admin: 管理员 - field_last_login_on: 最后登录 - field_language: 语言 - field_effective_date: 日期 - field_password: 密码 - field_new_password: 新密码 - field_password_confirmation: 确认 - field_version: 版本 - field_type: 类型 - field_host: 主机 - field_port: 端口 - field_account: 帐号 - field_base_dn: Base DN - field_attr_login: 登录名属性 - field_attr_firstname: 名字属性 - field_attr_lastname: 姓氏属性 - field_attr_mail: 邮件属性 - field_onthefly: 即时用户生成 - field_start_date: 开始日期 - field_done_ratio: "% 完成" - field_auth_source: 认证模式 - field_hide_mail: 隐藏我的邮件地址 - field_comments: 注释 - field_url: URL - field_start_page: 起始页 - field_subproject: 子项目 - field_hours: 小时 - field_activity: 活动 - field_spent_on: 日期 - field_identifier: 标识 - field_is_filter: 作为过滤条件 - field_issue_to: 相关问题 - field_delay: 延期 - field_assignable: 问题可指派给此角色 - field_redirect_existing_links: 重定向到现有链接 - field_estimated_hours: 预期时间 - field_column_names: 列 - field_time_entries: 工时 - field_time_zone: 时区 - field_searchable: 可用作搜索条件 - field_default_value: 默认值 - field_comments_sorting: 显示注释 - field_parent_title: 上级页面 - field_editable: 可编辑 - field_watcher: 跟踪者 - field_identity_url: OpenID URL - field_content: 内容 - field_group_by: 根据此条件分组 - field_sharing: 共享 - field_parent_issue: 父任务 - field_member_of_group: 用户组的成员 - field_assigned_to_role: 角色的成员 - field_text: 文本字段 - field_visible: 可见的 - - setting_app_title: 应用程序标题 - setting_app_subtitle: 应用程序子标题 - setting_welcome_text: 欢迎文字 - setting_default_language: 默认语言 - setting_login_required: 要求认证 - setting_self_registration: 允许自注册 - setting_attachment_max_size: 附件大小限制 - setting_issues_export_limit: 问题导出条目的限制 - setting_mail_from: 邮件发件人地址 - setting_bcc_recipients: 使用密件抄送 (bcc) - setting_plain_text_mail: 纯文本(无HTML) - setting_host_name: 主机名称 - setting_text_formatting: 文本格式 - setting_wiki_compression: 压缩Wiki历史文档 - setting_feeds_limit: RSS Feed内容条数限制 - setting_default_projects_public: 新建项目默认为公开项目 - setting_autofetch_changesets: 自动获取程序变更 - setting_sys_api_enabled: 启用用于版本库管理的Web Service - setting_commit_ref_keywords: 用于引用问题的关键字 - setting_commit_fix_keywords: 用于解决问题的关键字 - setting_autologin: 自动登录 - setting_date_format: 日期格式 - setting_time_format: 时间格式 - setting_cross_project_issue_relations: 允许不同项目之间的问题关联 - setting_issue_list_default_columns: 问题列表中显示的默认列 - setting_emails_header: 邮件头 - setting_emails_footer: 邮件签名 - setting_protocol: 协议 - setting_per_page_options: 每页显示条目个数的设置 - setting_user_format: 用户显示格式 - setting_activity_days_default: 在项目活动中显示的天数 - setting_display_subprojects_issues: 在项目页面上默认显示子项目的问题 - setting_enabled_scm: 启用 SCM - setting_mail_handler_body_delimiters: 在这些行之后截断邮件 - setting_mail_handler_api_enabled: 启用用于接收邮件的服务 - setting_mail_handler_api_key: API key - setting_sequential_project_identifiers: 顺序产生项目标识 - setting_gravatar_enabled: 使用Gravatar用户头像 - setting_gravatar_default: 默认的Gravatar头像 - setting_diff_max_lines_displayed: 查看差别页面上显示的最大行数 - setting_file_max_size_displayed: 允许直接显示的最大文本文件 - setting_repository_log_display_limit: 在文件变更记录页面上显示的最大修订版本数量 - setting_openid: 允许使用OpenID登录和注册 - setting_password_min_length: 最短密码长度 - setting_new_project_user_role_id: 非管理员用户新建项目时将被赋予的(在该项目中的)角色 - setting_default_projects_modules: 新建项目默认启用的模块 - setting_issue_done_ratio: 计算问题完成度: - setting_issue_done_ratio_issue_field: 使用问题(的完成度)属性 - setting_issue_done_ratio_issue_status: 使用问题状态 - setting_start_of_week: 日历开始于 - setting_rest_api_enabled: 启用REST web service - setting_cache_formatted_text: 缓存格式化文字 - setting_default_notification_option: 默认提醒选项 - setting_commit_logtime_enabled: 激活时间日志 - setting_commit_logtime_activity_id: 记录的活动 - setting_gantt_items_limit: 在甘特图上显示的最大记录数 - - permission_add_project: 新建项目 - permission_add_subprojects: 新建子项目 - permission_edit_project: 编辑项目 - permission_select_project_modules: 选择项目模块 - permission_manage_members: 管理成员 - permission_manage_project_activities: 管理项目活动 - permission_manage_versions: 管理版本 - permission_manage_categories: 管理问题类别 - permission_view_issues: 查看问题 - permission_add_issues: 新建问题 - permission_edit_issues: 更新问题 - permission_manage_issue_relations: 管理问题关联 - permission_add_issue_notes: 添加说明 - permission_edit_issue_notes: 编辑说明 - permission_edit_own_issue_notes: 编辑自己的说明 - permission_move_issues: 移动问题 - permission_delete_issues: 删除问题 - permission_manage_public_queries: 管理公开的查询 - permission_save_queries: 保存查询 - permission_view_gantt: 查看甘特图 - permission_view_calendar: 查看日历 - permission_view_issue_watchers: 查看跟踪者列表 - permission_add_issue_watchers: 添加跟踪者 - permission_delete_issue_watchers: 删除跟踪者 - permission_log_time: 登记工时 - permission_view_time_entries: 查看耗时 - permission_edit_time_entries: 编辑耗时 - permission_edit_own_time_entries: 编辑自己的耗时 - permission_manage_news: 管理新闻 - permission_comment_news: 为新闻添加评论 - permission_view_documents: 查看文档 - permission_manage_files: 管理文件 - permission_view_files: 查看文件 - permission_manage_wiki: 管理Wiki - permission_rename_wiki_pages: 重定向/重命名Wiki页面 - permission_delete_wiki_pages: 删除Wiki页面 - permission_view_wiki_pages: 查看Wiki - permission_view_wiki_edits: 查看Wiki历史记录 - permission_edit_wiki_pages: 编辑Wiki页面 - permission_delete_wiki_pages_attachments: 删除附件 - permission_protect_wiki_pages: 保护Wiki页面 - permission_manage_repository: 管理版本库 - permission_browse_repository: 浏览版本库 - permission_view_changesets: 查看变更 - permission_commit_access: 访问提交信息 - permission_manage_boards: 管理讨论区 - permission_view_messages: 查看帖子 - permission_add_messages: 发表帖子 - permission_edit_messages: 编辑帖子 - permission_edit_own_messages: 编辑自己的帖子 - permission_delete_messages: 删除帖子 - permission_delete_own_messages: 删除自己的帖子 - permission_export_wiki_pages: 导出 wiki 页面 - permission_manage_subtasks: 管理子任务 - permission_view_journals_for_messages: 查看留言 - - project_module_issue_tracking: 问题跟踪 - project_module_time_tracking: 时间跟踪 - project_module_news: 新闻 - project_module_documents: 文档 - project_module_files: 资料下载 - project_module_wiki: Wiki - project_module_repository: 版本库 - project_module_boards: 讨论区 - project_module_calendar: 日历 - project_module_gantt: 甘特图 - label_module_share: DTS测试工具 - - label_user: 用户 - label_user_plural: 用户列表 - label_user_new: 新建用户 - label_user_anonymous: 匿名用户 - label_project: 项目 - label_activity_project: '项目: ' #added by bai - label_project_new: 新建项目 - label_project_new_description: '项目可以是软件开发项目,也可以是协作研究项目。' - label_project_plural: 项目列表 - label_x_projects: - zero: 无项目 - one: 1 个项目 - other: "%{count} 个项目" - label_project_all: 所有的项目 - label_project_latest: 最近的项目 - label_issue: 问题 - label_issue_new: 新建问题 - label_issue_plural: 缺陷 - label_issue_view_all: 查看所有问题 - label_issues_by: "按 %{value} 分组显示问题" - label_issue_added: 问题已添加 - label_issue_updated: 问题已更新 - label_document: 文档 - label_document_new: 新建文档 - label_document_plural: 文档 - label_document_added: 文档已添加 - label_role: 角色 - label_role_plural: 角色 - label_role_new: 新建角色 - label_role_and_permissions: 角色和权限 - label_member: 成员 - label_member_new: 添加成员 - label_member_plural: 成员 - label_tracker: 跟踪标签 - label_tracker_plural: 跟踪标签 - label_tracker_new: 新建跟踪标签 - label_workflow: 工作流程 - label_issue_status: 问题状态 - label_issue_status_plural: 问题状态 - label_issue_status_new: 新建问题状态 - label_issue_category: 问题类别 - label_issue_category_plural: 问题类别 - label_issue_category_new: 新建问题类别 - label_custom_field: 自定义属性 - label_custom_field_plural: 自定义属性 - label_custom_field_new: 新建自定义属性 - label_enumerations: 枚举值 - label_enumeration_new: 新建枚举值 - label_information: 信息 - label_information_plural: 信息 - label_please_login: 请登录 - label_register: 注册 - label_login_with_open_id_option: 或使用OpenID登录 - label_password_lost: 忘记密码 - label_home: 主页 - #by young - label_requirement: 需求 - label_new_course: 课程列表 - label_course_practice: 课程实践 - label_course_all: 课程列表 - label_teacher_all: 所有教师 - label_project_deposit: 项目托管 - label_software_user: 软件创客 - label_contest_innovate: 创新竞赛 - label_requirement_enterprise: 软件众包 - label_requirement_enterprise_list: 众包列表 - label_new_homework: 作业 - label_new_contest: 竞赛 - label_requirement_focus: 关注需求 - label_developer: 用户 - label_account_developer: 开发者 - label_enterprise_into: 进入企业 - label_college_into: 进入高校 - label_investor: 投资人: - lable_contest_user: 竞赛发布人: #huang - label_user_home: 创客空间 - label_user_location: 当前位置 - label_course_term: 开课学期 - label_theme: 主题 - label_logged_as_new: 当前用户 - button_register: 注册 - issue_list: 缺陷列表 - lastest_respond: 最新反馈 - label_respond_view_all: 其他120个反馈 - label_news_lastest: 最新动态 - label_version_display_settings: 显示设置 - label_versions_progress: 完成进度 - label_versions_description: 版本描述 - label_my_photo: 我的头像 - label_documents_sort: 排序设置: - label_activities_settings: 显示设置 - label_user_login_new: 登录 - label_user_login_tips: 您还没有登录,请登录后留言 - label_user_login_course_board: 您还没有登录,请登录后参与课程讨论 - label_user_login_project_board: 您还没有登录,请登录后参与项目讨论 - label_user_login_attending_contest: 您还没有登录,请登录后参赛 - label_user_login_score_and_comment: 您还没有登录,请登录后对作品进行打分评价 - #end - #by huang # modified by bai - label_college: 高校进入 - label_enter_college: 进入高校 - label_enterprise: 企业进入 - lable_enter_enterprise: 进入企业 - label_term: 开课学期 - label_spring: 春季学期 - label_summer: 夏季学期 - label_autumn: 秋季学期 - label_winter: 冬季学期 - label_followers: 关注 - label_teacher: 教师 - label_teacher_list: 教师列表 - label_student_list: 学生列表 - label_limit_time: 截止日期 - label_commit_homework: 提交作业 - label_course_homework: 对应课程 - label_course_doing: 进行中的课程 - label_course_done: 已结束的课程 - label_homework_response: 作业咨询 - label_bidding_homework: 提交作业 - label_add_homework: 添加作业 - label_edit_homework: 修改作业 - label_delete_homework: 删除作业 - label_new_homework: 创建作业 - - #end - label_my_page: 我的工作台 - label_my_account: 我的帐号 - label_my_message: 留言 - label_my_projects: 我的项目 - label_my_page_block: 我的工作台模块 - label_administration: 管理 - label_login: 登录 - label_logout: 退出 - label_help: 帮助 - label_reported_issues: 已报告的问题 - label_assigned_to_me_issues: 指派给我的问题 - label_last_login: 最后登录 - label_registered_on: 注册于 - label_activity: 动态 # modified by bai - label_overall_activity: 活动概览 - label_user_activity: "%{value} 的活动" - label_new: 新建 - label_new_user: 注册了一个新用户 # added by bai - label_logged_as: 登录为 - label_environment: 环境 - label_authentication: 认证 - label_auth_source: 认证模式 - label_auth_source_new: 新建认证模式 - label_auth_source_plural: 认证模式 - label_subproject_plural: 子项目 - label_subproject_new: 新建子项目 - label_and_its_subprojects: "%{value} 及其子项目" - label_min_max_length: 最小 - 最大 长度 - label_list: 列表 - label_date: 日期 - label_integer: 整数 - label_float: 浮点数 - label_boolean: 布尔值 - label_string: 字符串 - label_text: 文本 - label_attribute: 属性 - label_attribute_plural: 属性 - label_no_data: 没有任何数据可供显示 - label_change_status: 变更状态 - label_history: 历史记录 - label_attachment: 文件 - label_attachment_new: 新建文件 - label_file_upload: 上传资料 - label_attachment_delete: 删除文件 - label_attachment_plural: 文件 - label_file_added: 文件已添加 - label_report: 报表 - label_report_plural: 报表 - label_news: 新闻 - label_news_new: 添加新闻 - bale_news_notice: 添加通知 #huang - label_news_notice: 发布课程通知 - label_news_plural: 新闻 - label_news_latest: 最近的新闻 - label_news_view_all: 查看所有新闻 - label_news_added: 新闻已添加 - label_settings: 配置 - label_overview: 项目动态 - label_course_overview: "课程动态" - label_question_student: 作业交流 #bai - label_homework_commit: 提交作业 #huang - label_homework_info: 提交情况 #huang - label_course_news: 课程通知 - label_course_news_description: '课程必须是高校正式开设的课程,或是围绕特定主题定期发布课程资料的公共开放课程;
如果您想创建一个协作研究空间,请您前往“我的项目”页面创建项目,谢谢!' - label_course_board: 讨论区 - label_version: 版本 - label_version_new: 新建版本 - label_version_plural: 版本 - label_close_versions: 关闭已完成的版本 - label_confirmation: 确认 - label_export_to: 导出 - label_read: 读取... - label_public_projects: 公开的项目 - label_open_issues: 打开 - label_open_issues_plural: 打开 - label_closed_issues: 已关闭 - label_closed_issues_plural: 已关闭 - label_x_open_issues_abbr_on_total: - zero: 0 打开 / %{total} - one: 1 打开 / %{total} - other: "%{count} 打开 / %{total}" - label_x_open_issues_abbr: - zero: 0 打开 - one: 1 打开 - other: "%{count} 打开" - label_x_closed_issues_abbr: - zero: 0 已关闭 - one: 1 已关闭 - other: "%{count} 已关闭" - label_total: 合计 - label_permissions: 权限 - label_current_status: 当前状态 - label_new_statuses_allowed: 允许的新状态 - label_all: 全部 - label_none: 无 - label_nobody: 无人 - label_next: 下一页 - label_previous: 上一页 - label_used_by: 使用中 - label_details: 详情 - label_add_note: 添加说明 - label_per_page: 每页 - label_calendar: 日历 - label_months_from: 个月以来 - label_gantt: 甘特图 - label_internal: 内部 - label_last_changes: "最近的 %{count} 次变更" - label_change_view_all: 查看所有变更 - label_personalize_page: 个性化定制本页 - label_comment: 评论 - label_comment_plural: 评论 - label_x_comments: - zero: 无评论 - one: 1 条评论 - other: "%{count} 条评论" - label_comment_add: 添加评论 - label_comment_added: 评论已添加 - label_comment_delete: 删除评论 - label_query: 自定义查询 - label_query_plural: 自定义查询 - label_query_new: 新建查询 - label_filter_add: 增加过滤器 - - label_filter_plural: 查询条件 - label_equals: 等于 - label_not_equals: 不等于 - label_in_less_than: 剩余天数小于 - label_in_more_than: 剩余天数大于 - label_greater_or_equal: '>=' - label_less_or_equal: '<=' - label_in: 剩余天数 - label_today: 今天 - label_all_time: 全部时间 - label_yesterday: 昨天 - label_this_week: 本周 - label_last_week: 上周 - label_last_n_days: "最后 %{count} 天" - label_this_month: 本月 - label_last_month: 上月 - label_this_year: 今年 - label_date_range: 日期范围 - label_less_than_ago: 之前天数少于 - label_more_than_ago: 之前天数大于 - label_ago: 之前天数 - label_contains: 包含 - label_not_contains: 不包含 - label_day_plural: 天 - label_repository: 版本库 - label_course_repository: 代码库 - label_repository_plural: 版本库 - label_browse: 浏览 - label_branch: 分支 - label_tag: 标签 - label_add_tag: "+ 添加标签" - label_revision: 修订 - label_revision_plural: 修订 - label_revision_id: 修订 %{value} - label_associated_revisions: 相关修订版本 - label_added: 已添加 - label_modified: 已修改 - label_copied: 已复制 - label_renamed: 已重命名 - label_deleted: 已删除 - label_latest_revision: 最近的修订版本 - label_latest_revision_plural: 最近的修订版本 - label_view_revisions: 查看修订 - label_view_all_revisions: 查看所有修订 - label_no_file_uploaded: 未上传文件 - label_max_size: 最大文件大小 - label_sort_highest: 置顶 - label_sort_higher: 上移 - label_sort_lower: 下移 - label_sort_lowest: 置底 - label_roadmap: 里程碑 #版本路线图 - label_roadmap_due_in: "截止日期到 %{value}" - label_roadmap_overdue: "%{value} 延期" - label_roadmap_no_issues: 该版本没有问题 - label_search: 搜索 - label_search_projects: 搜索项目 - label_search_topics: 搜索帖子 - label_result_plural: 结果 - label_all_words: 所有单词 - label_wiki: Wiki - label_wiki_edit: Wiki 编辑 - label_wiki_edit_plural: Wiki 编辑记录 - label_wiki_page: Wiki 页面 - label_wiki_page_plural: Wiki 页面 - label_index_by_title: 按标题索引 - label_index_by_date: 按日期索引 - label_current_version: 当前版本 - label_preview: 预览 - label_feed_plural: Feeds - label_changes_details: 所有变更的详情 - label_issue_tracking: 问题跟踪 - label_spent_time: 耗时 - label_overall_spent_time: 总体耗时 - label_f_hour: "%{value} 小时" - label_f_hour_plural: "%{value} 小时" - label_time_tracking: 时间跟踪 - label_change_plural: 变更 - label_statistics: 统计 - label_contest: 竞赛 - label_commits_per_month: 每月提交次数 - label_commits_per_author: 每用户提交次数 - label_view_diff: 查看差别 - label_diff_inline: 直列 - label_diff_side_by_side: 并排 - label_options: 选项 - label_copy_workflow_from: 从以下选项复制工作流程 - label_permissions_report: 权限报表 - label_watched_issues: 跟踪的问题 - label_related_issues: 相关的问题 - label_applied_status: 应用后的状态 - label_loading: 载入中... - label_relation_new: 新建关联 - label_relation_delete: 删除关联 - label_relates_to: 关联到 - label_duplicates: 重复 - label_duplicated_by: 与其重复 - label_blocks: 阻挡 - label_blocked_by: 被阻挡 - label_precedes: 优先于 - label_follows: 跟随于 - label_end_to_start: 结束-开始 - label_end_to_end: 结束-结束 - label_start_to_start: 开始-开始 - label_start_to_end: 开始-结束 - label_stay_logged_in: 保持登录状态 - label_disabled: 禁用 - label_show_completed_versions: 显示已完成的版本 - label_me: 我 - label_board: 讨论区 - label_board_new: 新建讨论区 - label_board_plural: 讨论区 - label_board_locked: 锁定 - label_board_sticky: 置顶 - field_sticky: '' - field_locked: '' - field_lock: '' - label_topic_plural: 主题 - label_message_plural: 帖子 - label_message_last: 最新的帖子 - label_message_new: 发布新帖 - label_message_posted: 发帖成功 - label_reply_plural: 回复 - label_send_information: 给用户发送帐号信息 - label_year: 年 - label_month: 月 - label_week: 周 - label_date_from: 从 - label_date_to: 到 - label_language_based: 根据用户的语言 - label_sort_by: "根据 %{value} 排序" - label_send_test_email: 发送测试邮件 - label_feeds_access_key: RSS存取键 - label_missing_feeds_access_key: 缺少RSS存取键 - label_feeds_access_key_created_on: "RSS存取键是在 %{value} 之前建立的" - label_module_plural: 模块 - label_added_time_by: "由 %{author} 在 %{age} 之前添加" - label_added_time: "在 %{age} 之前添加" - label_updated_time: " 更新于 %{value} 之前" - label_updated_time_by: "由 %{author} 更新于 %{age} 之前" - label_jump_to_a_project: 选择一个项目... - label_file_plural: 文件 - label_changeset_plural: 变更 - label_default_columns: 默认列 - label_no_change_option: (不变) - label_bulk_edit_selected_issues: 批量修改选中的问题 - label_theme: 主题 - label_default: 默认 - label_search_titles_only: 仅在标题中搜索 - label_user_mail_option_all: "收取我的项目的所有通知" - #huang - label_file_new: 下载 - label_user_edit: "修改资料" - label_user_info: "个人简介" #huang 添加 - label_user_watcher: "关注" # huang添加的 - label_user_fans: "粉丝" - # modify by men - label_x_user_fans: - zero: 粉丝 - one: 粉丝 - other: 粉丝 - #end - label_x_join_in_contest: - zero: 参与者 - one: 参与者 - other: 参与者 - #end - label_user_commits: "代码提交" - label_user_watchered: "关注" # huang添加的 - label_user_newfeedback: "留言" ## huang添加的 - label_feedback_success: "留言成功" - label_feedback_fail: "留言失败" - label_user_login: "最后登录" - label_user_mail: "邮件地址" - label_user_joinin: "加入时间" - label_user_activities: 您没有关注该用户,请尝试重新输入! - label_user_activities_other: 该用户暂无任何动态! - label_project_overview: "概述" - label_project_tool: "项目工具集" - label_project_issues: "缺陷" - label_project_newother: "查看其他评论" - label_project_newshare: "分享了" - label_project_notice: "发布了通知:" - label_project_newadd: "添加了" - label_project_unadd: "暂无项目,赶快去创建吧!" - label_project_un: "该用户暂未参与任何项目!" - label_project_course_un: "该用户暂未加入任何课程!" - label_project_course_unadd: "你还未创建课程,赶快去创建吧!" - label_project_cousre_studentun: "你还未加入任何课程,赶快加入吧!" - #end by huang - label_user_mail_option_selected: "收取选中项目的所有通知..." - label_user_mail_option_none: "不收取任何通知" - label_user_mail_option_only_my_events: "只收取我跟踪或参与的项目的通知" - label_user_mail_option_only_assigned: "只收取分配给我的" - label_user_mail_option_only_owner: 只收取由我创建的 - label_user_mail_no_self_notified: "不要发送对我自己提交的修改的通知" - label_registration_activation_by_email: 通过邮件认证激活帐号 - label_registration_manual_activation: 手动激活帐号 - label_registration_automatic_activation: 自动激活帐号 - label_display_per_page: "每页显示:%{value}" - label_age: 提交时间 - label_change_properties: 修改属性 - label_general: 一般 - label_more: 更多>> - label_scm: SCM - label_plugins: 插件 - label_ldap_authentication: LDAP 认证 - label_downloads_abbr: D/L - label_optional_description: 可选的描述 - label_add_another_file: 添加其它文件 - label_preferences: 首选项 - label_chronological_order: 按时间顺序 - label_reverse_chronological_order: 按时间顺序(倒序) - label_planning: 计划 - label_incoming_emails: 接收邮件 - label_generate_key: 生成一个key - label_issue_watchers: 跟踪者 - label_example: 示例 - label_display: 显示 - label_sort: 排序 - label_ascending: 升序 - label_descending: 降序 - label_date_from_to: 从 %{start} 到 %{end} - label_wiki_content_added: Wiki 页面已添加 - label_wiki_content_updated: Wiki 页面已更新 - label_group: 组 - label_group_plural: 组 - label_group_new: 新建组 - label_time_entry_plural: 耗时 - label_version_sharing_none: 不共享 - label_version_sharing_descendants: 与子项目共享 - label_version_sharing_hierarchy: 与项目继承层次共享 - label_version_sharing_tree: 与项目树共享 - label_version_sharing_system: 与所有项目共享 - label_update_issue_done_ratios: 更新问题的完成度 - label_copy_source: 源 - label_copy_target: 目标 - label_copy_same_as_target: 与目标一致 - label_display_used_statuses_only: 只显示被此跟踪标签使用的状态 - label_api_access_key: API访问键 - label_missing_api_access_key: 缺少API访问键 - label_api_access_key_created_on: API访问键是在 %{value} 之前建立的 - label_profile: 简介 - label_subtask_plural: 子任务 - label_project_copy_notifications: 复制项目时发送邮件通知 - label_principal_search: "搜索用户或组:" - label_user_search: "搜索用户:" - - button_login: 登录 - button_submit: 提交 - button_save: 保存 - button_check_all: 全选 - button_uncheck_all: 清除 - button_delete: 删除 - button_create: 提交 #bai - button_create_and_continue: 创建并继续 - button_test: 测试 - button_edit: 编辑 - button_edit_associated_wikipage: "编辑相关wiki页面: %{page_title}" - button_add: 新增 - button_change: 修改 - button_ok_and_submit: 确定并提交 - - button_apply: 查询 - button_clear: 清除留言 - button_clear_requirement: 取消 - button_lock: 锁定 - button_unlock: 解锁 - button_download: 下载 - button_list: 列表 - button_view: 查看 - button_move: 移动 - button_move_and_follow: 移动并转到新问题 - button_back: 返回 - button_cancel: 取消 - button_activate: 激活 - button_sort: 排序 - button_log_time: 登记工时 - button_rollback: 恢复到这个版本 - button_watch: 跟踪 - button_unwatch: 取消跟踪 - button_reply: 回复 - button_archive: 存档 - button_unarchive: 取消存档 - button_reset: 重置 - button_rename: 重命名/重定向 - button_change_password: 修改密码 - button_copy: 复制 - button_copy_and_follow: 复制并转到新问题 - button_annotate: 追溯 - button_update: 更新 - button_configure: 配置 - button_quote: 引用 - button_duplicate: 副本 - button_show: 显示 - - status_active: 活动的 - status_registered: 已注册 - status_locked: 已锁定 - - version_status_open: 打开 - version_status_locked: 锁定 - version_status_closed: 关闭 - - field_active: 活动 - - text_select_mail_notifications: 选择需要发送邮件通知的动作 - text_regexp_info: 例如:^[A-Z0-9]+$ - text_min_max_length_info: 0 表示没有限制 - text_project_destroy_confirmation: 您确信要删除这个项目以及所有相关的数据吗? - text_subprojects_destroy_warning: "以下子项目也将被同时删除:%{value}" - text_workflow_edit: 选择角色和跟踪标签来编辑工作流程 - text_are_you_sure: 您确定要删除吗? - text_are_you_sure_out: 你确定要退出该课程吗? - text_journal_changed: "%{label} 从 %{old} 变更为 %{new}" - text_journal_set_to: "%{label} 被设置为 %{value}" - text_journal_deleted: "%{label} 已删除 (%{old})" - text_journal_added: "%{label} %{value} 已添加" - text_tip_issue_begin_day: 今天开始的任务 - text_tip_issue_end_day: 今天结束的任务 - text_tip_issue_begin_end_day: 今天开始并结束的任务 - text_caracters_maximum: "最多 %{count} 个字符。" - text_caracters_minimum: "至少需要 %{count} 个字符。" - text_length_between: "长度必须在 %{min} 到 %{max} 个字符之间。" - text_command: 学生或其他成员申请加入课程时候需要使用该口令,该口令可以由老师在课堂上公布。 - text_contest_reward: 选择奖励后输入描述。 - text_tracker_no_workflow: 此跟踪标签未定义工作流程 - text_unallowed_characters: 非法字符 - text_comma_separated: 可以使用多个值(用逗号,分开)。 - text_line_separated: 可以使用多个值(每行一个值)。 - text_issues_ref_in_commit_messages: 在提交信息中引用和解决问题 - text_issue_added: "问题 %{id} 已由 %{author} 提交。" - text_issue_updated: "问题 %{id} 已由 %{author} 更新。" - text_wiki_destroy_confirmation: 您确定要删除这个 wiki 及其所有内容吗? - text_issue_category_destroy_question: "有一些问题(%{count} 个)属于此类别。您想进行哪种操作?" - text_issue_category_destroy_assignments: 删除问题的所属类别(问题变为无类别) - text_issue_category_reassign_to: 为问题选择其它类别 - text_user_mail_option: "对于没有选中的项目,您将只会收到您跟踪或参与的项目的通知(比如说,您是问题的报告者, 或被指派解决此问题)。" - text_no_configuration_data: "角色、跟踪标签、问题状态和工作流程还没有设置。\n强烈建议您先载入默认设置,然后在此基础上进行修改。" - text_load_default_configuration: 载入默认设置 - text_status_changed_by_changeset: "已应用到变更列表 %{value}." - text_time_logged_by_changeset: "已应用到修订版本 %{value}." - text_issues_destroy_confirmation: '您确定要删除选中的问题吗?' - text_select_project_modules: '请选择此项目可以使用的模块:' - text_default_administrator_account_changed: 默认的管理员帐号已改变 - text_file_repository_writable: 附件路径可写 - text_plugin_assets_writable: 插件的附件路径可写 - text_rmagick_available: RMagick 可用(可选的) - text_destroy_time_entries_question: 您要删除的问题已经上报了 %{hours} 小时的工作量。您想进行那种操作? - text_destroy_time_entries: 删除上报的工作量 - text_assign_time_entries_to_project: 将已上报的工作量提交到项目中 - text_reassign_time_entries: '将已上报的工作量指定到此问题:' - text_user_wrote: "%{value} 写到:" - text_enumeration_destroy_question: "%{count} 个对象被关联到了这个枚举值。" - text_enumeration_category_reassign_to: '将它们关联到新的枚举值:' - text_email_delivery_not_configured: "邮件参数尚未配置,因此邮件通知功能已被禁用。\n请在config/configuration.yml中配置您的SMTP服务器信息并重新启动以使其生效。" - text_repository_usernames_mapping: "选择或更新与版本库中的用户名对应的Trustie用户。\n版本库中与Trustie中的同名用户将被自动对应。" - text_diff_truncated: '... 差别内容超过了可显示的最大行数并已被截断' - text_custom_field_possible_values_info: '每项数值一行' - text_wiki_page_destroy_question: 此页面有 %{descendants} 个子页面和下级页面。您想进行那种操作? - text_wiki_page_nullify_children: 将子页面保留为根页面 - text_wiki_page_destroy_children: 删除子页面及其所有下级页面 - text_wiki_page_reassign_children: 将子页面的上级页面设置为 - text_own_membership_delete_confirmation: 你正在删除你现有的某些或全部权限,如果这样做了你可能将会再也无法编辑该项目了。你确定要继续吗? - text_zoom_in: 放大 - text_zoom_out: 缩小 - - default_role_manager: 管理人员 - default_role_developer: 开发人员 - default_role_reporter: 报告人员 - default_tracker_bug: 错误 - default_tracker_feature: 功能 - default_tracker_support: 支持 - default_issue_status_new: 新建 - default_issue_status_in_progress: 进行中 - default_issue_status_resolved: 已解决 - default_issue_status_feedback: 反馈 - default_issue_status_closed: 已关闭 - default_issue_status_rejected: 已拒绝 - default_doc_category_user: 用户文档 - default_doc_category_tech: 技术文档 - default_priority_low: 低 - default_priority_normal: 普通 - default_priority_high: 高 - default_priority_urgent: 紧急 - default_priority_immediate: 立刻 - default_activity_design: 设计 - default_activity_development: 开发 - - enumeration_issue_priorities: 问题优先级 - enumeration_doc_categories: 文档类别 - enumeration_activities: 活动(时间跟踪) - enumeration_system_activity: 系统活动 - - field_warn_on_leaving_unsaved: 当离开未保存内容的页面时,提示我 - text_warn_on_leaving_unsaved: 若离开当前页面,则该页面内未保存的内容将丢失。 - label_my_queries: 我的自定义查询 - text_journal_changed_no_detail: "%{label} 已更新。" - label_news_comment_added: 添加到新闻的评论 - button_expand_all: 展开所有 - button_collapse_all: 合拢所有 - label_additional_workflow_transitions_for_assignee: 当用户是问题的分配对象时所允许的问题状态转换 - label_additional_workflow_transitions_for_author: 当用户是问题作者时所允许的问题状态转换 - label_bulk_edit_selected_time_entries: 批量修改选定的时间条目 - text_time_entries_destroy_confirmation: 是否确定要删除选定的时间条目? - label_role_anonymous: Anonymous - label_role_non_member: Non member - label_issue_note_added: 问题备注已添加 - label_issue_status_updated: 问题状态更新 - label_issue_priority_updated: 问题优先级更新 - label_issues_visibility_own: 创建或分配给用户的问题 - field_issues_visibility: 问题可见 - label_issues_visibility_all: 全部问题 - permission_set_own_issues_private: 设置自己的问题为公开或私有 - field_is_private: 私有 - permission_set_issues_private: 设置问题为公开或私有 - label_issues_visibility_public: 全部非私有问题 - text_issues_destroy_descendants_confirmation: 此操作同时会删除 %{count} 个子任务。 - - field_commit_logs_encoding: 提交注释的编码 - field_scm_path_encoding: 路径编码 - text_scm_path_encoding_note: "默认: UTF-8" - field_path_to_repository: 库路径 - field_root_directory: 根目录 - field_cvs_module: CVS Module - field_cvsroot: CVSROOT - text_mercurial_repository_note: 本地库 (e.g. /hgrepo, c:\hgrepo) - text_scm_command: 命令 - text_scm_command_version: 版本 - label_git_report_last_commit: 报告最后一次文件/目录提交 - text_scm_config: 您可以在config/configuration.yml中配置您的SCM命令。 请在编辑后,重启Redmine应用。 - text_scm_command_not_available: Scm命令不可用。 请检查管理面板的配置。 - text_git_repository_note: 库中无内容。(e.g. /gitrepo, c:\gitrepo) - notice_issue_successful_create: 问题 %{id} 已创建。 - label_between: 介于 - setting_issue_group_assignment: 允许问题被分配给组 - label_diff: diff - description_query_sort_criteria_direction: 排序方式 - description_project_scope: 搜索范围 - description_filter: 过滤器 - description_user_mail_notification: 邮件通知设置 - description_date_from: 输入开始日期 - description_message_content: 信息内容 - description_available_columns: 备选列 - description_date_range_interval: 按开始日期和结束日期选择范围 - description_issue_category_reassign: 选择问题类别 - description_search: 搜索字段 - description_notes: 批注 - description_date_range_list: 从列表中选择范围 - description_choose_project: 项目 - description_date_to: 输入结束日期 - description_query_sort_criteria_attribute: 排序方式 - description_wiki_subpages_reassign: 选择父页面 - description_selected_columns: 已选列 - label_parent_revision: 父修订 - label_child_revision: 子修订 - error_scm_annotate_big_text_file: 输入文本内容超长,无法输入。 - setting_default_issue_start_date_to_creation_date: 使用当前日期作为新问题的开始日期 - button_edit_section: 编辑此区域 - setting_repositories_encodings: 附件和版本库编码 - description_all_columns: 所有列 - button_export: 导出 - label_export_options: "%{export_format} 导出选项" - error_attachment_too_big: 该文件无法上传。超过文件大小限制 (%{max_size}) - notice_failed_to_save_time_entries: "无法保存下列所选取的 %{total} 个项目中的 %{count} 工时: %{ids}。" - label_x_issues: - zero: 0 问题 - one: 1 问题 - other: "%{count} 问题" - #add by tan - label_repository_new: 连接到已有的SVN版本库 - label_repository_no: 还没有版本库? - label_repository_new_repos: 新建版本库 - label_repository_name: 版本库名 - #end - field_repository_is_default: 主版本库 - label_copy_attachments: 复制附件 - label_item_position: "%{position}/%{count}" - label_completed_versions: 已完成的版本 - text_project_identifier_info: 仅小写字母(a-z)、数字、破折号(-)和下划线(_)可以使用。
一旦保存,标识无法修改。 - field_multiple: 多重取值 - setting_commit_cross_project_ref: 允许引用/修复所有其他项目的问题 - text_issue_conflict_resolution_add_notes: 添加说明并取消我的其他变更处理。 - text_issue_conflict_resolution_overwrite: 直接套用我的变更 (先前的说明将被保留,但是某些变更内容可能会被覆盖) - notice_issue_update_conflict: 当您正在编辑这个问题的时候,它已经被其他人抢先一步更新过了。 - text_issue_conflict_resolution_cancel: 取消我所有的变更并重新刷新显示 %{link} 。 - permission_manage_related_issues: 相关问题管理 - field_auth_source_ldap_filter: LDAP 过滤器 - label_search_for_watchers: 通过查找方式添加跟踪者 - notice_account_deleted: 您的账号已被永久删除(账号已无法恢复)。 - setting_unsubscribe: 允许用户退订 - button_delete_my_account: 删除我的账号 - text_account_destroy_confirmation: |- - 确定继续处理? - 您的账号一旦删除,将无法再次激活使用。 - error_session_expired: 您的会话已过期。请重新登陆。 - text_session_expiration_settings: "警告: 更改这些设置将会使包括你在内的当前会话失效。" - setting_session_lifetime: 会话最大有效时间 - setting_session_timeout: 会话闲置超时 - label_session_expiration: 会话过期 - permission_close_project: 关闭/重开项目 - label_show_closed_projects: 查看已关闭的项目 - button_close: 关闭 - button_reopen: 重开 - project_status_active: 已激活 - project_status_closed: 已关闭 - project_status_archived: 已存档 - text_project_closed: 当前项目已被关闭。当前项目只读。 - notice_user_successful_create: 用户 %{id} 已创建。 - field_core_fields: 标准字段 - field_timeout: 超时 (秒) - setting_thumbnails_enabled: 显示附件略缩图 - setting_thumbnails_size: 略缩图尺寸 (像素) - label_status_transitions: 状态转换 - label_fields_permissions: 字段权限 - label_readonly: 只读 - label_required: 必填 - text_repository_identifier_info: 仅小写字母(a-z)、数字、破折号(-)和下划线(_)可以使用。
一旦保存,标识无法修改。 - field_board_parent: 父论坛 - label_attribute_of_project: 项目 %{name} - label_attribute_of_author: 作者 %{name} - label_attribute_of_assigned_to: 分配给 %{name} - label_attribute_of_fixed_version: 目标版本 %{name} - label_copy_subtasks: 复制子任务 - label_copied_to: 复制到 - label_copied_from: 复制于 - label_any_issues_in_project: 项目内任意问题 - label_any_issues_not_in_project: 项目外任意问题 - field_private_notes: 私有注解 - permission_view_private_notes: 查看私有注解 - permission_set_notes_private: 设置为私有注解 - label_no_issues_in_project: 项目内无相关问题 - label_any: 全部 - label_last_n_weeks: 上 %{count} 周前 - setting_cross_project_subtasks: 支持跨项目子任务 - label_cross_project_descendants: 与子项目共享 - label_cross_project_tree: 与项目树共享 - label_cross_project_hierarchy: 与项目继承层次共享 - label_cross_project_system: 与所有项目共享 - button_hide: 隐藏 - setting_non_working_week_days: Non-working days - label_in_the_next_days: in the next - label_in_the_past_days: in the past - label_attribute_of_user: User's %{name} - text_turning_multiple_off: If you disable multiple values, multiple values will be - removed in order to preserve only one value per item. - label_attribute_of_issue: Issue's %{name} - permission_add_documents: Add documents - permission_edit_documents: Edit documents - permission_delete_documents: Delete documents - label_gantt_progress_line: Progress line - setting_jsonp_enabled: Enable JSONP support - field_inherit_members: Inherit members - field_closed_on: Closed - setting_default_projects_tracker_ids: Default trackers for new projects - label_total_time: 合计 - label_create_time: 创建时间 #Customer added!Added by nie - label_comment_time: 留言时间 - label_activity_time: 发布时间 - label_update_time: 更新时间 - label_current_contributors: 位当前贡献者 - label_commit_limit: 作业提交时间已过! - label_commit_ar: 作业提交截止时间快到了! - #modify by men - label_x_download_num: - zero: 次下载 - one: 次下载 - other: 次下载 - #end - label_lines_of_code: 行代码 - label_view_num: 次浏览 - label_users_on_trustie: 用户 - label_front: 第一页 - label_commit_on: 次提交 - label_uncommit_homework: 暂无学生提交作业! - #modify by men - label_x_commit_on: - zero: 次提交 - one: 次提交 - other: 次提交 - #end - label_follow_people: 个关注者 - #modify by men - label_x_followers_num: - zero: 个关注者 - one: 个关注者 - other: 个关注者 - #end - label_match_score: 关联度 - label_hot_value: 热度 - label_member_since: 加入 - label_contribute_to: 参与了 %{project_count} 个项目: - #modify by men - label_x_contribute_to: - zero: 参与了 %{count} 个项目: - one: 参与了 %{count} 个项目: - other: 参与了 %{count} 个项目: - #end - label_total_commit: 共%{total_commit}次提交 - #modify by men - label_x_total_commit: - zero: 共 %{count} 次提交 - one: 共 %{count} 次提交 - other: 共 %{count} 次提交 - #end - label_upload_profile: 上传头像 - label_type_as: 类型为 - label_status_as: 状态为 - label_priority_as: 优先级为 - label_member_list: 成员列表 - label_author_name: 由%{author_name}发表了 - label_comments_count: (%{count}条评论) - label_post_on: 发表了 - label_find_all_comments: 查看所有评论 - label_updated_time_on: " 更新于 %{value} " - label_call_list: 需求列表 - #added by liuping - button_unfollow: 取消关注 - button_follow: 关注 - label_followers: 关注 - label_responses: 留言 - label_delete_confirm: 确认删除? - label_more_tags: 更多 - label_tags_bid: 需求名称 - label_tags_course_name: 课程名称 - label_tags_bid_description: 需求描述 - label_tags_issue_description: 问题描述 - label_tags_all_objects: 所有 - label_apply_project: 申请加入 - label_apply_project_waiting: 已处理申请,请等待管理员审核 - label_unapply_project: 取消申请 - - #fq - button_leave_meassge: 留言 - label_leave_message_to: 给用户 %{name}留言 - label_leave_message: 留言内容 - label_message: 留言板 - field_add: 添加于 %{time} 之前 - button_more: 更多 - label_user_response: 用户留言 - label_student_response: 作业答疑 # modified by bai - label_bidding_project: 参与项目 - label_homework_project: 已提交作业 #huang - button_bidding: 我要参加 - field_enterprise: '企业:' - - no_attachmens_allowed: 提交作业不能为空 - - button_bidding_homework: 参加竞标 #huang - field_homework_type: 提交形式 #bai - label_homework_respond: 作业情况 - - label_bid_me: 我要应标 - label_new_call: 发布需求 - - label_newtype_contest: 发布竞赛 - - label_user_information: "与我相关" - label_bid_succeed: "需求发布成功" - label_wrong_budget: 错误的金额格式 - label_wrong_date: 时间格式错误,请输入正确的时间 yyyy-mm-dd - label_bidding_succeed: 应标成功 - label_bidding_contest_succeed: 竞赛提交成功 #added by bai - label_bidding_homework_succeed: 作业提交成功 #added by bai - label_bidding_homework_failed: 作业提交失败 #added by bai - label_bidding_homework_committed: 你已经提交过作业,不能重复提交! - label_bidding_fail: 应标失败,该项目已经应标 - label_bidding_homework_fail: 作业提交失败,该作业已经被提交! - - label_requirement_list: 需求列表 - - label_x_biding_project: #modify by men - zero: 应标项目 - one: 应标项目 - other: 应标项目 - #end - label_x_homework_project: #modify by huang - zero: 已提交的作业 - one: 已提交的作业 - other: 已提交的作业 - #end - label_x_responses: #modify by men - zero: 留言 - one: 留言 - other: 留言 - #end - label_x_responses: #modify by huang - zero: 学生提问 - one: 学生提问 - other: 学生提问 - #end - label_x_bids_responses: #modify by huang - zero: 用户反馈 - one: 用户反馈 - other: 用户反馈 - #end - label_x_followers: #modify by men - zero: 关注 - one: 关注 - other: 关注 - #end - label_price: 悬赏: - label_RMB_sign: ¥ - label_investment_budget: 投资预算: - label_investment_time_limit: 投资时限: - label_my_respond: 如有问题请在这里留下您的宝贵意见^-^ - label_my_question: 请在此处留下您的意见或者问题~ # modified by bai - label_respond_requirement: 对需求进行了反馈 - label_contest_requirement: 对竞赛进行了反馈 - label_question_requirement: 对作业提出了问题! - label_deadline: 投资时限yyyy-mm-dd - label_requirement_name: 在此输入需求名称 - label_contest_name: 在此输入竞赛名称 - label_requirement_description: 内容:对你的需求进行描述 - label_contest_description: 内容:对你的竞赛进行描述 - label_requirement_bargain_money: 输入具体奖励方式(如金钱、奖项、学分) - button_upload_photo: 上传图片 - label_leave_me_message: 给我留言了 - label_leave_others_message: 给他留言了 - label_leave_a_message: 给他(她)留言 - label_leave_your_message: 给你留言了 - label_new_activity: 有了最新动态 - label_create_project: 参与了 - label_praise: 赞 - label_cancel_praise: 取消赞 - label_bid_reason: 请输入参与理由 - label_bid_reason_homework: 请输入作业提交说明! - label_create_new_projects: 创建项目 - label_call_for_bids: 发布需求 - label_create_course: 创建课程 - label_news: 新闻 - label_milestone: 里程碑 - label_features: 特性 - label_has_praisers: 赞(%{count}) - label_has_watchers: 关注(%{count}) - label_has_fans: 粉丝(%{count}) - label_coursefile_sharingarea: 课程文件共享专区 - #modify by men - label_x_has_fans: - zero: 粉丝(%{count}) - one: 粉丝(%{count}) - other: 粉丝(%{count}) - #end - label_me: 我 - label_my: 我 - label_i: 我 - label_you: 你 - label_join_bidding: 参与了应标 - label_jion_bidding_homework: 已提交! - label_bidding_user: 应标人: - label_bidding_user_homework: 作业提交者 - label_bidding_user_studentcode: 学号 - label_bidding_reason: 应标宣言: - label_bidding_reason_homewrok: 作业提交说明 - label_username: 用户名: - label_password: 密码: - label_about_requirement: 对需求: - label_about_issue: 对问题: - label_quote_my_words: 中对我的话进行了引用 - label_have_respond: 进行了反馈 - label_in_issues: 在问题: - label_in_bids: 在需求: - label_in_users: 在用户: - label_have_respond: 进行了反馈 - label_create_new_projects_description: 创建项目,让我们开启一次神奇的协同创作和开发之旅! - label_call_for_bids_description: 发布需求,征集解决方案,体验一呼百应的兴奋感觉! - label_news_description: 实时了解项目的最新动态,掌握最新项目咨询! - label_milestone_description: 在这里您可以看见任何一个版本的工程! - label_have_respond: 进行了反馈 - label_welcome: 欢迎 - label_join: 加入Trustie! - label_board_description: 七嘴八舌,汇聚众人智慧,为您排忧解难! - label_create_course_description: 课程小社区,创建新课程,让我们共同分享多到想不到的公共资源! - label_welcome_page_to: 参与了 %{project_count} 个项目! - label_repository_path_not_null: 库路径 不能为空字符 - label_password_not_null: 密码不能设置为空。 - label_exist_repository_path: 定义已有版本库URL路径,定义格式file:///, http://, https://, svn:// - label_project_no_activity: 该项目暂无动态! - label_course_homework_un: 暂未发布任何作业 - label_follow_no_requirement: 暂未关注任何需求! - label_no_user_respond_you: 暂无任何用户对您进行反馈! - label_tags_issue: 问题名称: - label_tags_project_name: 项目名称: - label_tags_project_description: 项目描述: - label_tags_user_mail: 用户邮箱: - label_tags_user_name: 用户名: - label_tags_numbers: Tag统计: - label_max_number: 至多25个字符。 - label_mail_attention: qq邮箱可能收不到此邮件,其他邮箱如果没有收到可能在垃圾邮件中,其中gmail与教育网邮箱的激活邮件有时比较慢,请耐心等待。 - label_all_revisions: 所有版本: - label_upassword_info: 该密码在项目组内可共享 - label_how_commit_code: 查看如何提交代码: - label_how_commit_code_chinese: 中文 -# modified by bai - label_welcome_leave_message: 您好!系统目前正在公测,有意见和建议请 - label_welcome_click_me: 点击我 - label_issue_praise: 好问题,顶! - label_issue_tread: 烂问题,踩! - label_issue_praise_over: 我刚才顶过了~ - label_issue_tread_over: 我刚才踩过了~ - #end - label_goto: 前往>> - label_issue_appraise_over: 只能评价一次哦! - label_welcome_my_respond: 请在此留下你的意见和建议! - label_no_current_fans: 该用户暂无粉丝 - label_no_current_watchers: 该用户暂未关注其他用户 - label_project_tool_response: 用户反馈 - label_course_feedback: 留言 - label_tags_search_result: 搜索结果 - label_active_call: 需求 - label_active_homework: 作业 - label_tags_call: 需求 - label_user_extensions: 其他信息 - label_boy: 男 - label_girl: 女 - field_gender: 性别 - field_birthday: 生日 - field_brief_introduction: 个人简介 - field_location: 现住址 - field_occupation: 工作单位 - field_work_experience: 工作经验(年) - field_zip_code: 邮编 - label_reward: 奖励: - label_credit: 学分: - label_choose_reward: 选择奖励方式 - label_money: 货币 - label_reward_1: 其他 - label_bids_credit: 学分 - label_bids_credit_number: 分 - field_budget: 奖励 - field_deadline: 截止日期 - label_tags_selected: 已选标签 - label_tags_related: 相关标签 - button_project_tags_add: 添加 - label_issue_query_condition: 查询条件 - label_issue_query: 查询 - label_issue_cancel_query: 取消查询 - field_reward_type: 奖励类型 - label_tags_no: 暂无标签! - label_course_description_no: 你还未对该课程添加描述! - label_bid_publish: 发布了 - label_bid_project: 项目 - label_project_no_follow: 该项目暂未被关注! - label_no_bid_project: 暂无参与项目 - label_no_course_project: 暂无已提交的作业! - label_bids_reward_method: 奖励方式 : - label_bids_reward_what: 输入奖励内容 - label_call_bonus: 奖金 - label_bids_form_new_description: 企业可以在此发布一个软件开发任务或者一个技术方案需求:(1)获得价廉物美的解决方案;(2)发现对此项任务有贡献的大学生,获得可以招聘的人才。 - label_bids_form_contest_new_description: 企业或者高校可以在此发布一个竞赛。 - label_homeworks_form_new_description: 发布一个作业,作业提交方式可以是附件或者项目形式,在作业类型里面设置。 - label_fork_form_new_description: 该需求将作为某课程的作业被发布,作业提交方式可以使附件或者项目形式,在作业类型里面设置。 - label_bids_new_money: 输入奖励金额,如 500,2.5等 - label_bids_new_credit: 输入该作业对应课程的学分,如 3,2.5等 - label_bids_new_content: 输入奖励内容,如 奖项,物品等 - label_project_sort: 排序方式 - label_sort_by_time: 按时间排序 - label_sort_by_active: 按活跃度排序 - label_sort_by_influence: 按影响力排序 - label_bids_published: 发布于 - label_bids_published_ago: 之前 - label_welcome_trustie: Trustie - label_welcome_trustie_project: 在线项目托管平台 - label_welcome_trustie_course: 在线课程实践平台 - label_welcome_trustie_contest: 在线竞赛实战平台 - label_welcome_trustie_osscean: -OSSEAN - label_welcome_trustie_project_description: 面向中国大学生与软件从业者,提供社交化的项目管理、代码托管、资源共享、合作交流。 - label_welcome_trustie_course_description: 面向中国高校教师与大学生,提供社交化的课程管理、资源共享、合作实验、协同研究。 - label_welcome_trustie_contest_description: 面向中国大学生与编程爱好者,提供社交化的竞赛管理、应用管理、代码托管、合作交流。 - label_welcome_trustie_osscean_description: 基于全球开源社区数据的软件搜索与态势分析平台 - label_user_project: 项目 - label_user_course: 课程 - label_user_homework: 作业 - label_bid_respond_quote: 回复 - label_bid_if_agreement: 如果喜欢我,请点击我 - label_bid_respond_delete: 删除 - label_newfeedback_message: 留言 - label_newfeedback_quote: 回复 - label_newfeedback_delete: 删除 - label_user_all_activity: 所有动态 - label_user_activity_myself: 我的动态 # modified by bai - label_my_honework_no_homework: 暂无任何作业! - label_user_all_respond: 所有反馈 - label_layouts_feedback: 留言 - label_have_feedback: 有了 - label_of_feedback: 的 - label_welcome_participate: 参与了 - #modify by men - label_x_welcome_participate: - zero: 参与了 - one: 参与了 - other: 参与了 - #end - label_welcome_participate_project: 个项目 - label_projects_feedback: 对项目进行了反馈 - label_projects_feedback_respond: 回复 - label_projects_feedback_respond_success: 回复成功 - button_projects_feedback_respond: 回复 - label_projects_feedback_respond_content: 请输入回复内容 - label_user_create_project: 创建了 - label_user_create_project_homework: 创建了作业 -#added by bai - label_identity: 身份 - label_teacher: 教师 - label_teacher_homework: 教师姓名 - label_student: 学生 - label_TA: 助教 - label_other: 其他 - label_enterprise: 企业 - label_developer: 用户 - label_gender: 性别 - label_gender_male: 男 - label_gender_female: 女 - label_location: 地区 - label_brief_introduction: 个性签名 - label_my_brief_introduction: 今天的心情如何?留下你的脚印吧~ - label_time: 年度 - label_main_teacher: 主讲教师 - label_main_term: 课程学期 - label_teacher_work_unit: 教师单位 - label_course_time: 课程年度 - label_i_new_activity: 有了新活动在 - label_choose_course: 选择课程 - button_submit_homework: 提交作业 - label_my_course: 我的课程 - button_submit_bid: 参与竞标 - label_requirement_from: 需求来源 - label_course_view: 作业界面 - label_course_return: "返 回 课 程" - label_setup_time: 开课日期 - label_endup_time: 结课日期 - label_class_period: 学时总数 - label_class_hour: 学时 - label_user_score: 个人综合得分 - label_user_score_of_topic: 帖子得分 - label_user_score_of_project: 项目得分 - label_user_score_of_activity: 活跃度得分 - label_user_score_of_influence: 影响力得分 - label_question_top: 问题被顶次数 - label_question_down: 问题被踩次数 - label_answer_top: 回答被顶次数 - label_answer_down: 回答被踩次数 - label_comments_number: 评论的数量 - label_news_number: 新闻的数量 - label_wiki_number: wiki的数量 - label_message_number: 留言的数量 - label_activity_number: 个人动态数量 - label_issue_message_number: 对issue的留言数量 - label_code_submit_number: 代码提交次数 - label_topic_number: 讨论区发言数量 - label_projects_score: 项目综合得分 - label_issue_score: issue得分 - label_news_score: 新闻得分 - label_file_score: 文档得分 - label_code_submit_score: 代码提交得分 - label_topic_score: 讨论区得分 - label_issue_number: issue的数量 - label_issue_journal_number: issue的留言数量 - label_new_number: 新闻的数量 - label_file_number: 文档的数量 - label_code_submit_number: 代码提交数量 - label_topic_number: 讨论区帖子数量 - - label_course_contribute_to: 参与了 %{project_count} 个项目: - label_x_course_contribute_to: - zero: "参与了 %{count} 个课程:" - one: "参与了 %{count} 个课程:" - other: "参与了 %{count} 个课程:" - - label_join_contest: 加入竞赛 - label_exit_contest: 退出竞赛 - label_participator: 参与者 - label_contest_modify_settings: 配置竞赛 - label_no_current_participate: 该竞赛暂无参与者 - - #end - - label_joined_course: 参加的课程 - label_created_course: 创建的课程 - label_course: 课程 - label_course_new: 新建课程 - label_course_join_student: 加入课程 - label_public_info: (打钩为公开,不打钩则不公开,若不公开,仅项目成员可见该项目。) - label_course_view_student: 查看其他课程 - label_course_student: 学生 - label_homework: 课程作业 - label_course_file: 资源库 #资料共享 - label_stores_index: 资源搜索 - label_course_new_homework: 新建作业 - label_course_homework_list: 作业列表 - label_course_homework_new: 发布作业 - label_fork_homework_new: 选为作业 - - label_x_course_data: - zero: 资料 - one: 资料 - other: 资料 - label_x_base_courses_student: - zero: 学生 - one: 学生 - other: 学生 - label_x_base_courses_teacher: - zero: 教师 - one: 教师 - other: 教师 - - label_homework_statistics: 作业统计 - label_technical_title: 职称 - - # added by william 无english版本 - label_bidding_results: 应标结果 - label_bid_end: 该需求已经结束! - label_special_reward: 特等奖 - label_first_reward: 一等奖 - label_second_reward: 二等奖 - label_third_reward: 三等奖 - label_fourth_reward: 四等奖 - label_fifth_reward: 五等奖 - label_excellence_reward: 优秀奖 - label_comfort_reward: 入围奖 - label_course_settings: 课程设置 - -#added by nie - label_x_task: - zero: 份作业 - one: 份作业 - other: 份作业 - label_x_member: - zero: 个成员 - one: 个成员 - other: 个成员 - label_x_data: - zero: 份资料 - one: 份资料 - other: 份资料 - - - - #add by men - label_technicl_title_professor: 教授 - label_technicl_title_associate_professor: 副教授 - label_technicl_title_lecturer: 讲师 - label_technicl_title_teaching_assistant: 助教 - label_account_identity_teacher: 教师 - label_account_identity_student: 学生 - label_account_identity_developer: 开发者 - label_account_identity_enterprise: 企业 - label_account_identity_choose: --请选择身份-- - label_teaching_course: 我执教的课程 - label_release_homework: 我发布的作业 - label_enterprise_into: 进入企业 - label_homework_source: 作业来源 - label_course_college: 大学 - label_my_create_honework_no_homework: 暂无任何作业 - label_my_homework_no_homework: 暂无任何作业 - label_bid_show_course_name: 课程名称 - label_bid_show_teacher_name: 教师 - label_bid_contest_show_course_name: 课程名称 - label_bid_contest_show_teacher_name: 教师 - label_contest_list: 竞赛列表 - - label_x_base_courses_member: - zero: 成员 - one: 成员 - other: 成员 - - label_bids_task_list: 作业列表 - label_join_course: 加入课程 - label_exit_course: 退出课程 - label_new_join: 加入 - label_new_course_password: 课程密码 - label_new_course_school: 开课学校 - label_new_course_description: 课程描述 - label_new_join_order: 请输入课程密码 - label_task_submit_form_accessory: 作业最终以附件形式提交 - label_task_submit_form_project: 作业最终以项目形式提交 - label_has_been: 已经被 - label_course_userd_by: 个课程引用 - - role_of_course: 课程角色 - label_student: 学生 - - #added by Wen - label_school_all: 中国高校 - - - label_project_grade: 项目得分 - label_user_grade: 个人得分 - label_user_for_project_grade: 个人得分 - label_system_grade: 系统评分 - label_teacher: 老师 - label_ta: 助教 - label_in_course: 在课程中 - label_assign_homework: 中布置了作业 - label_noawards: 未评奖 - - label_course_modify_settings: 配置课程 - label_homework_prompt: 贴心小提示: - label_homework_prompt_content: 亲,在这里我们的作业将以项目的形式提交,如果小伙伴们还没有创建项目,请先创建一个项目。项目创建成功后,就可以 - label_create_homework: 布置了作业: - label_watch_project: 关注了 - label_watch_no_projects: 没有关注任何项目 - label_has_watched_project: 关注的项目 - label_project_take: 参与的项目 - label_peoject_take_in: 加入了项目: - label_search_by_user: 按用户搜索 - label_update_homework_succeed: 作业更新成功 - label_task_plural: 作业 - label_search_by_student_id: 按学号过滤 - label_institution_name: 单位名称 - label_duration_time: 授课时间 - label_course_brief_introduction: 课程简介 - field_teacher_name: 教 师 - - field_hidden_repo: 隐藏代码库 - - label_newbie_faq: '新手指引 & 问答' - label_hot_project: '热门项目' - label_borad_project: 项目讨论区 - label_borad_course: 课程讨论区 - label_memo_create_succ: 发布成功 - label_memo_create_fail: 发布失败 - label_forum_create_succ: 贴吧新建成功 - label_forum_create_fail: 贴吧新建失败 - label_forum_edit: 编辑讨论区 - label_memo_create: 发布 - label_memo_new: 新建主题 - label_memo_edit: 修改主题label_board_new - label_memo_new_from_forum: 发布帖子 - label_forum: 公共贴吧 - label_forum_new: 新建贴吧 - label_tags_forum_description: 贴吧描述 - label_tags_forum: 贴吧名称 - label_project_module_forums: 公共贴吧 - label_memo_locked: 帖子已被锁定 - label_downloads_list: 进入附件列表 - label_joined_contest: 参与了竞赛 - label_contest_user: 参赛人: - label_contest_reason: 参赛宣言: - label_notification: 通知 - label_sumbit_empty: 搜索内容不能为空 - no_use: 没有帮助 - cancel_no_use: 撤销没有帮助 - cancel_apply: 取消申请 - apply_master: 申请成为版主 - you_are_master: 您是该项目的版主 - - #add by linchun (竞赛相关) - label_upload_files: 上传文件 - label_upload_softwarepackage: 上传软件包 - label_upload_cuttingphoto: 上传截图 - label_contests_reward_method: 奖励方式 - label_system_platform: 系统平台 - label_nextstep: 下一步 - label_participate: 参赛者 - label_setting: 配置 - label_contest_project: 参赛项目 - label_contest_softapplication: 参赛应用 - label_contest_response: 用户反馈 - label_contest_watchers: 关注人数 - label_contest_application: 参赛应用 - label_contest_work: 参赛作品 - button_contesting_as_project: 我要参赛(新建项目) - button_contesting_as_application: 我要参赛(发布应用) - label_release_softapplication: 发布应用 - label_upload_softapplication_packets: 上传应用软件包 - label_upload_softapplication_photo: 上传产品截图 - label_upload_softapplication_packets_mustpacketed: 作品相关代码及相关说明文件必须打包后以压缩包的形式上传,便于上传和下载 ; - label_upload_softapplication_photo_condition: 作品截图需上传0~4张;格式为gif/jpg/png, 每张小于5M - label_updated_caution: 注意:若编辑参赛作品,则之前上传的软件包和截图都将被删除,请重新上传! - label_softapplication_name: 应用名称 - label_work_name: 作品名称 - label_softapplication_description: 应用简介 - label_work_description: 作品简介 - label_work_scores: 作品得分 - label_work_rating: 评分 - label_work_tishi: 您可以重新打分,打分结果以最后一次打分为主! - label_work_scores_proportion: 得分比例 - label_softapplication_type: 应用分类 - label_work_type: 作品分类 - label_work_photo: 作品截图 - label_work_comment: 作品评论 - label_softapplication_version_available: 适配版本 - label_running_platform: 运行平台 - label_softapplication_developer: 上传人员 - label_softapplication_developers: 开发人员 - label_work_deposit_project_url: 托管项目网址 - label_work_deposit_project: 托管项目 - label_softapplication_name_condition: 25个汉字以内(50个字符) - label_softapplication_description_condition: 125个汉字以内 - label_user_login_softapplication_board: 您还没有登录,请登录后参与应用评价。 - label_contest_description_no: 暂无描述。 - label_no_contest_softapplication: 暂无参赛应用 - label_button_ok: 确定 - label_tags_contest: 竞赛标签 - label_tags_contest: 竞赛名称 - label_final_scores: 最终得分 - label_rating_person_amount: 打分总人数 - label_tags_contest_description: 竞赛描述 - label_release_add_contest_succeed: 该应用发布并添加成功. - label_add_contest_succeed_fail: 添加失败,该应用已参赛. - label_no_ftapplication: 暂无应用 - label_edit_softapplication: 修改应用 - label_edit_work: 修改作品 - label_contest_delete: 删除竞赛 - label_softapplication_list: 应用列表 - label_contest_work_list: 参赛作品列表 - label_attending_contest: 我要参赛 - label_contest_notification: 竞赛通知 - - label_coursefile_sharingarea: 课程资源共享区 - label_sort_by_activity: 按动态数排序 - label_homework: 课程实践 - label_x_activity: - zero: 个动态 - one: 个动态 - other: 个动态 - label_school_all: 中国高校 - label_upload_files: 上传资源 - label_relation_files: 关联已有资源 - label_contest_settings: 配置竞赛 - label_contest_delete: 删除竞赛 - label_noawards_current: 暂未评奖 - - label_softapplication: 应用软件 - label_attending_contest: 参加竞赛 - label_new_attendingcontest_work: 新建参赛作品 - label_workname_lengthlimit: 25个汉字以内 - label_workdescription_lengthlimit: 125个汉字以内 - label_please_input_password: 请输入竞赛密码 - label_please_select_project: 请选择项目 - label_upload_softworkpacket_photo: 上传作品软件包和作品截图 - label_reward: 评奖 - label_please_select_contestingsoftapplication: 请选择参赛应用 - label_attendingcontest_time: 参赛时间 - label_attendingcontest_spoksman: 参赛代表 - label_wellmeaning_intimation_contentone: 温馨提示:如果您准备参加竞赛,请点击下面的"新建参赛作品"! - label_wellmeaning_intimation_contenttwo: 若您已完成开发,且只希望发布您的作品,“托管项目”一项可以不选; - label_wellmeaning_intimation_contentthree: 若您希望托管竞赛数据和代码以及保留开发和提交代码的轨迹,请从“托管项目”中选择一项您已创建好的项目作为该参赛作品的托管项目,若您还没有创建项目,请点击右边的“创建项目”,然后回到本页再选择。 - - notice_account_updated: 帐号更新成功 - notice_attendingcontest_work_successfully_created: 恭喜您,参赛作品创建成功! - notice_softapplication_was_successfully_updated: 恭喜您,参赛作品更新成功! - - label_attendingcontestwork_belongs_contest: 所属竞赛 - label_attendingcontestwork_belongs_type: 所属类别 - label_attendingcontestwork_release_person: 发布人员 - label_attendingcontestwork_adaptive_system: 系统支持 - label_attendingcontestwork_download: 作品下载 - label_attendingcontestwork_developers: 开发人员 - label_attendingcontestwork_average_scores: 平均评分 - label_attendingcontestwork_release_time: 发布时间 - label_attendingcontestwork_deposit_project: 托管项目 - label_attendingcontestwork_sorting_intimation: 您可以重新打分,打分结果以最后一次打分为主! - - #end - - # ajax异步验证 - modal_valid_passing: 可以使用 - label_bug: 漏洞 - - #gcm - ###################### - label_project_safety_state: 项目安全态势 - label_technology_trend: 技术创新趋势 - label_popularity_trend: 项目全球热度趋势 - label_unit_ten_thousand: 万 - label_unit_one_hundred_million: 亿 - label_topics_search: 帖子搜索 - ####################### - - ############帖子 - label_review_num: 个回复 - label_view_num: 次浏览 - label_collection_num: 次收藏 - ############帖子 - #gcm end - - #layout#base_opensource_p - label_osp_community: 开源项目社区 - label_base_osp_view_num: 浏览数 - label_base_osp_discuss_num: 讨论数 - label_base_osp_download_num: 下载数 - label_osp_source: 项目来源 - label_apply_project_master: 版主申请 - #layout#base_opensource_p - - #open_source_projects - label_safety_analysis: 安全态势分析 - #open_source_projects - - label_x_relative_topics_count: 点影响力 - diff --git a/trustie2/config/preinitializer.rb b/trustie2/config/preinitializer.rb deleted file mode 100644 index 90f789c6d..000000000 --- a/trustie2/config/preinitializer.rb +++ /dev/null @@ -1,20 +0,0 @@ -begin - require "rubygems" - require "bundler" -rescue LoadError - $stderr.puts "Redmine requires Bundler. Please install it with `gem install bundler`." - exit 1 -end - -if Gem::Version.new(Bundler::VERSION) < Gem::Version.new("1.0.21") - $stderr.puts "Redmine requires Bundler 1.0.21 (you're using #{Bundler::VERSION}).\nPlease install a newer version with `gem install bundler`." - exit 1 -end - -begin - ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__) - Bundler.setup -rescue Bundler::GemNotFound - $stderr.puts "Some gems may need to be installed or updated.\nPlease run `bundle install --without development test`." - exit 1 -end diff --git a/trustie2/config/puma.rb b/trustie2/config/puma.rb deleted file mode 100644 index c79f9e1f5..000000000 --- a/trustie2/config/puma.rb +++ /dev/null @@ -1,7 +0,0 @@ -environment "production" -bind "unix:///var/run/ossean.sock" -restart_command '/var/www/ossean/trustie2/restart_puma' -daemonize true -pidfile "/var/tmp/pids/puma.pid" -#stdout_redirect "/var/www/ossean/trustie2/log/stdout", "/var/www/ossean/trustie2/log/stderr" - diff --git a/trustie2/config/routes.rb b/trustie2/config/routes.rb deleted file mode 100644 index 49117f169..000000000 --- a/trustie2/config/routes.rb +++ /dev/null @@ -1,672 +0,0 @@ -# Redmine - project management software -# Copyright (C) 2006-2013 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 tobthe Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -RedmineApp::Application.routes.draw do - - root :to => 'open_source_projects#welcome', :as => 'home' - resources :welcome - resources :homework_users - - resources :no_uses - delete 'no_uses', :to => 'no_uses#delete' - - resources :apply_project_masters - delete 'apply_project_masters', :to => 'apply_project_masters#delete' - - resources :relative_memos do - collection do - match 'search', via:[:get,:post] - end - end - - resources :open_source_projects do - collection do - match 'welcome', via: [:get] - match 'search', via: [:get, :post] - match 'search_all', via: [:get] - match 'remove_condition', via: [:get, :post] - match 'allbug', via: [:get, :post] - end - resources :relative_bugs - resources :relative_memos - member do - match 'master_apply', via: [:get, :post] - match 'accept_master_apply', via: [:get, :post] - match 'refuse_master_apply', via: [:get, :post] - match 'showmemo', via: [:get, :post] - match 'showbug', via: [:get, :post] - end - end - - match '/monitor', to: 'ossean_monitors#show', via: 'get' - match '/salarychart', to: 'ossean_highcharts#index' - match 'salarychart/:action', to: 'ossean_highcharts#:action' - - #添加stackoverflow_github项目推荐页面跳转链接 - match '/softwarerec', to: 'ossean_sta_git_matchs#index' - match 'softwarerec/:action', to: 'ossean_sta_git_matchs#:action' - - #添加open_source_project详情页面 echarts图表的ajax路由 - match 'echarts/:action', to: 'open_source_projects#:action' - #异步加载项目详情页的路由 - match 'tabs/show_memos_tab', to: 'open_source_projects#show_memos_tab' - match 'tabs/show_analysis_tab', to: 'open_source_projects#show_analysis_tab' - - #异步添加user行为记录到日志文件 - match 'user_traces/:action', to: 'user_traces#:action' - - - #分页加载关联帖子 - match 'show_memos_by_type', to: 'open_source_projects#show_memos_by_type' - - mount SeemsRateable::Engine => '/rateable', :as => :rateable - - namespace :zipdown do - match 'assort' - end - namespace :test do - match 'courselist' - match 'zip' - end - ##new added by linchun #以发布应用的形式参与竞赛 - resources :softapplications do - - collection do - match 'new_message', via: :get - end - member do - match 'create_message' , via: :post - end - end - - ## new added by linchun #新竞赛相关 - resources :contests, only: [:index] do - collection do - match 'new_contest' , via: :get - match 'join_in_contest' , via: :post - match 'unjoin_in_contest' , via: :delete - match 'create_contest' , via: :post - match 'new_join' , via: :post - match 'new' , via: :post - end - member do - match 'add_softapplication' - match 'update_contest' , via: [:put] - match 'show_contest' , via: :get - match 'show_project' , via: :get - match 'show_softapplication' , via: :get - match 'show_attendingcontest' , via: :get - match 'show_notification' , via: :get - match 'show_participator' , via: :get - match 'set_reward_project' , via: [:get, :post] - match 'set_reward_softapplication' , via: [:get, :post] - match 'add' , via: [:get, :post] - match 'add_softapplication' , via: [:get, :post] - match 'create' , via: :post - match 'settings' , via: [:get, :post] - end - end - - resources :stores do - collection do - match 'search', via: [:get, :post] - end - end - - resources :forums do - collection do - match 'search_forum', :via => [:get, :post] - end - member do - post 'create_memo' - match 'search_memo', :via => [:get, :post] - end - resources :memos do - collection do - get "quote" - end - end - end - - resources :shares - - #added by william - get "tags/index" - - get "tags/show" - - get "praise_tread/praise_plus" - - get "praise_tread/tread_plus" - #end - - - #added by baiyu - match 'git_usage/ch_usage', :controller => 'git_usage', :action => 'ch_usage', :via => :get, :as => 'ch_usage' - match 'git_usage/en_usage', :controller => 'git_usage', :action => 'en_usage', :via => :get, :as => 'en_usage' - #added by nie - match '/projects/search', :controller => 'projects', :action => 'search', :via => [:get, :post] - match '/users/search', :controller => 'users', :action => 'search', :via => [:get, :post] - - #added by zhangxunhui - match '/admin/monitor', :controller => 'ossean_monitors', :action => 'new', :via => [:get, :post] - - #end - match 'login', :to => 'account#login', :as => 'signin', :via => [:get, :post] - match 'logout', :to => 'account#logout', :as => 'signout', :via => [:get, :post] - match 'account/register', :to => 'account#register', :via => [:get, :post], :as => 'register' - match 'account/lost_password', :to => 'account#lost_password', :via => [:get, :post], :as => 'lost_password' - match 'account/activate', :to => 'account#activate', :via => :get - match 'account/valid_ajax', :to => 'account#valid_ajax', :via => :get - - match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put] - match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put] - match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put] - match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put] - - match 'projects/:id/wiki', :to => 'wikis#edit', :via => :post - match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post] - - # boards - match 'boards/:board_id/topics/new', :to => 'messages#new', :via => [:get, :post], :as => 'new_board_message' - get 'boards/:board_id/topics/:id', :to => 'messages#show', :as => 'board_message' - match 'boards/:board_id/topics/quote/:id', :to => 'messages#quote', :via => [:get, :post] - get 'boards/:board_id/topics/:id/edit', :to => 'messages#edit' - - post 'boards/:board_id/topics/preview', :to => 'messages#preview', :as => 'preview_board_message' - post 'boards/:board_id/topics/:id/replies', :to => 'messages#reply' - post 'boards/:board_id/topics/:id/edit', :to => 'messages#edit' - post 'boards/:board_id/topics/:id/destroy', :to => 'messages#destroy' - # boards end - post 'bids/homework_destroy', :to => 'bids#homework_destroy' - - get '/projects/:project_id/issues/calendar', :to => 'calendars#show', :as => 'project_calendar' - get '/issues/calendar', :to => 'calendars#show' - - get 'projects/:id/issues/report', :to => 'reports#issue_report', :as => 'project_issues_report' - get 'projects/:id/issues/report/:detail', :to => 'reports#issue_report_details', :as => 'project_issues_report_details' - post '/users/:id/user_activities', :to => 'users#show', :as => "user_activities" - - #added by young - resources :users do - collection do - match 'tag_disagree', :to => 'users#tag_disagree' - end - member do - match 'user_projects', :to => 'users#user_projects', :via => :get - match 'user_activities', :to => 'users#show', :via => :get, :as => "user_activities" - match 'user_newfeedback', :to => 'users#user_newfeedback', :via => :get, :as => "user_newfeedback" - match 'watch_calls', :controller => 'users', :action => 'watch_bids', :via => [:get , :post] - match 'info', :to => 'users#info', :via => [:get , :post], :as => 'user_info' - match 'user_watchlist', :to => 'users#user_watchlist', :via => :get, :as => "user_watchlist" #add by huang - match 'user_fanslist', :to => 'users#user_fanslist', :via => :get, :as => "user_fanslist" #add by huang - match 'user_courses', :to => 'users#user_courses', :via => :get - match 'user_homeworks', :to => 'users#user_homeworks', :via => :get - match 'watch_projects', :to => 'users#watch_projects', :via => :get - # added by bai - match 'show_score', :to => 'users#show_score', :via => :get - match 'topic_score_index', :controller => 'users', :action => 'topic_score_index', :via => [:get, :post] - match 'project_score_index', :to => 'users#project_score_index', :via => :get - match 'activity_score_index', :to => 'users#activity_score_index', :via => :get - match 'influence_score_index', :to => 'users#influence_score_index', :via => :get - match 'score_index', :to => 'users#score_index', :via => :get - - match 'show_projects_score', :to => 'projects#show_projects_score', :via => [:get, :post] - match 'issue_score_index', :to => 'projects#issue_score_index', :via => [:get, :post] - match 'news_score_index', :to => 'projects#news_score_index', :via => [:get, :post] - match 'file_score_index', :to => 'projects#file_score_index', :via => [:get, :post] - match 'code_submit_score_index', :to => 'projects#code_submit_score_index', :via => [:get, :post] - match 'projects_topic_score_index', :to => 'projects#projects_topic_score_index', :via => [:get, :post] - # end - end - end - match 'users/:id/user_newfeedback', :to => 'users#user_newfeedback', :via => :get, :as => "feedback" - match 'users/:id/user_projects', :controller => 'users', :action => 'user_projects', :via => :get - #match 'user/:id/watch_calls', :controller => 'users', :action => 'watch_bids', :via => [:get , :post] - - #end - match 'my/account', :controller => 'my', :action => 'account', :via => [:get, :post] - match 'my/account/destroy', :controller => 'my', :action => 'destroy', :via => [:get, :post] - match 'my/page', :controller => 'my', :action => 'page', :via => :get - match 'my', :controller => 'my', :action => 'index', :via => :get # Redirects to my/page - match 'my/reset_rss_key', :controller => 'my', :action => 'reset_rss_key', :via => :post - match 'my/reset_api_key', :controller => 'my', :action => 'reset_api_key', :via => :post - match 'my/password', :controller => 'my', :action => 'password', :via => [:get, :post] - match 'my/page_layout', :controller => 'my', :action => 'page_layout', :via => :get - match 'my/add_block', :controller => 'my', :action => 'add_block', :via => :post - match 'my/remove_block', :controller => 'my', :action => 'remove_block', :via => :post - match 'my/order_blocks', :controller => 'my', :action => 'order_blocks', :via => :post - - resources :users - match 'users/:id/memberships/:membership_id', :to => 'users#edit_membership', :via => :put, :as => 'user_membership' - match 'users/:id/memberships/:membership_id', :to => 'users#destroy_membership', :via => :delete - match 'users/:id/memberships', :to => 'users#edit_membership', :via => :post, :as => 'user_memberships' - ################# added by william - match 'users/tag_save', :to => 'users#tag_save', :via => :post, :as => 'tag' - match 'users/tag_saveEx', :to => 'users#tag_saveEx', :via => :post - #match 'users/tag_disagree', :to => 'users#tag_disagree' #:controller => 'users', :action => 'tag_disagree'#, :via => :get - - post 'watchers/watch', :to => 'watchers#watch', :as => 'watch' - delete 'watchers/watch', :to => 'watchers#unwatch' - get 'watchers/new', :to => 'watchers#new' - post 'watchers', :to => 'watchers#create' - post 'watchers/append', :to => 'watchers#append' - delete 'watchers', :to => 'watchers#destroy' - get 'watchers/autocomplete_for_user', :to => 'watchers#autocomplete_for_user' - # Specific routes for issue watchers API - post 'issues/:object_id/watchers', :to => 'watchers#create', :object_type => 'issue' - delete 'issues/:object_id/watchers/:user_id' => 'watchers#destroy', :object_type => 'issue' - - post 'appliedproject/applied', :to => 'applied_project#applied_join_project', :as => 'appliedproject' - delete 'appliedproject/applied', :to => 'applied_project#unapplied_join_project' - - resources :bids, :only=>[:edit,:update,:show] do - member do - match 'homework_ajax_modal' - end - end - resources :projects do - member do - post 'finishcourse' - post 'restartcourse' - get 'settings(/:tab)', :action => 'settings', :as => 'settings' - #by young - get 'member', :controller => 'projects', :action => 'member', :as => 'member' - get 'file', :action => 'file', :as => 'file' - get 'statistics', :action => 'statistics', :as => 'statistics' - get 'feedback', :action => 'feedback', :as => 'project_feedback' - get 'watcherlist', :action=> 'watcherlist' - match 'user_watcherlist', :to => 'projects#watcherlist', :via => :get, :as => "watcherlist" #add by huang - get 'homework', :action => 'homework', :as => 'homework' - get 'new_homework', :action => 'new_homework', :as => 'new_homework' - #get 'news', :action => 'news', :as => 'news' - #end - post 'modules' - post 'archive' - post 'unarchive' - post 'close' - post 'reopen' - match 'copy', :via => [:get, :post] - end - - #by young - match '/member', :controller => 'projects', :action => 'member', :as => 'member', :via => :get - match '/file', :controller => 'projects', :action => 'file', :as => 'file', :via => :get - match '/statistics', :controller => 'projects', :action => 'statistics', :as => 'statistics', :via => :get - # match '/investor', :controller => 'projects', :action => 'investor', :as => 'investor', :via => :get - match '/homework', :controller => 'projects', :action => 'homework', :as => 'homework', :via => :get - - # match '/activity', :controller => 'activities', :action => 'index', :as => 'activity', :via => :get - # match '/repository', :controller => 'repositories', :action => 'show', :repository_id => nil, :path => nil, :rev => nil, :as => 'repository', :via => :get - # match '/', :controller => 'projects', :action => 'show', :as => 'project_show', :via => :get - # get 'projects/:project_id/show', :to => 'projects#show', :as => 'project_show' - # get 'projects/:project_id/repository', :to => 'repositories#show', :as => 'project_repository' - - # match '/show', :controller => 'projects', :action => 'show', :as => 'project_show', :via => :get - match '/watcherlist', :controller=>'projects', :action=> 'watcherlist', :as => 'watcherlist', :via => :get #add by huang - # matche '/news', :controller => 'news', :action => 'index', :as => 'news', :via => :get - #end - - resources :memberships, :shallow => true, :controller => 'members', :only => [:index, :show, :new, :create, :update, :destroy] do - collection do - get 'autocomplete' - get 'appliedproject' - end - end - - resource :enumerations, :controller => 'project_enumerations', :only => [:update, :destroy] - - get 'issues/:copy_from/copy', :to => 'issues#new', :as => 'copy_issue' - resources :issues, :only => [:index, :new, :create] do - resources :time_entries, :controller => 'timelog' do - collection do - get 'report' - end - end - end - # issue form update - match 'issues/update_form', :controller => 'issues', :action => 'update_form', :via => [:put, :post], :as => 'issue_form' - - resources :files, :only => [:index, :new, :create] do - collection do - match "getattachtype" , via: [:get, :post] - #match 'getattachtype/:attachtype', :to => 'files#getattachtype', via: [:get, :post] - end - end - - resources :versions, :except => [:index, :show, :edit, :update, :destroy] do - collection do - put 'close_completed' - end - end - get 'versions.:format', :to => 'versions#index' - get 'roadmap', :to => 'versions#index', :format => false - get 'versions', :to => 'versions#index' - - resources :news, :except => [:show, :edit, :update, :destroy] - resources :time_entries, :controller => 'timelog' do - get 'report', :on => :collection - end - resources :queries, :only => [:new, :create] - resources :issue_categories, :shallow => true - resources :documents, :except => [:show, :edit, :update, :destroy] - resources :boards - resources :repositories, :shallow => true, :except => [:index, :show] do - member do - match 'committers', :via => [:get, :post] - end - end - resources :repositories, :except => [:index, :show] do - member do - get 'newrepo', :via => [:get, :post] - # get 'create', :via=>[:get, :post] - end - end - match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get - resources :wiki, :except => [:index, :new, :create], :as => 'wiki_page' do - member do - get 'rename' - post 'rename' - get 'history' - get 'diff' - match 'preview', :via => [:post, :put] - post 'protect' - end - collection do - get 'export' - get 'date_index' - end - end - match 'wiki', :controller => 'wiki', :action => 'show', :via => :get - get 'wiki/:id/:version', :to => 'wiki#show', :constraints => {:version => /\d+/} - delete 'wiki/:id/:version', :to => 'wiki#destroy_version' - get 'wiki/:id/:version/annotate', :to => 'wiki#annotate' - get 'wiki/:id/:version/diff', :to => 'wiki#diff' - end - - resources :issues do - collection do - match 'bulk_edit', :via => [:get, :post] - post 'bulk_update' - end - resources :time_entries, :controller => 'timelog' do - collection do - get 'report' - end - end - resources :relations, :shallow => true, :controller => 'issue_relations', :only => [:index, :show, :create, :destroy] - end - match '/issues', :controller => 'issues', :action => 'destroy', :via => :delete - - resources :queries, :except => [:show] - - resources :news, :only => [:index, :show, :edit, :update, :destroy] - match '/news/:id/comments', :to => 'comments#create', :via => :post - match '/news/:id/comments/:comment_id', :to => 'comments#destroy', :via => :delete - - resources :versions, :only => [:show, :edit, :update, :destroy] do - post 'status_by', :on => :member - end - - match '/time_entries/context_menu', :to => 'context_menus#time_entries', :as => :time_entries_context_menu, :via => [:get, :post] - - resources :time_entries, :controller => 'timelog', :except => :destroy do - collection do - get 'report' - get 'bulk_edit' - post 'bulk_update' - end - end - match '/time_entries/:id', :to => 'timelog#destroy', :via => :delete, :id => /\d+/ - # TODO: delete /time_entries for bulk deletion - match '/time_entries/destroy', :to => 'timelog#destroy', :via => :delete - - get 'projects/:id/activity', :to => 'activities#index' - get 'projects/:id/activity.:format', :to => 'activities#index' - get 'activity', :to => 'activities#index' - - # repositories routes - get 'projects/:id/repository/:repository_id/statistics', :to => 'repositories#stats' - get 'projects/:id/repository/:repository_id/graph', :to => 'repositories#graph' - - get 'projects/:id/repository/:repository_id/changes(/*path(.:ext))', :to => 'repositories#changes' - - get 'projects/:id/repository/:repository_id/revisions/:rev', :to => 'repositories#revision' - get 'projects/:id/repository/:repository_id/revision', :to => 'repositories#revision' - post 'projects/:id/repository/:repository_id/revisions/:rev/issues', :to => 'repositories#add_related_issue' - delete 'projects/:id/repository/:repository_id/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue' - get 'projects/:id/repository/:repository_id/revisions', :to => 'repositories#revisions' - get 'projects/:id/repository/:repository_id/revisions/:rev/:action(/*path(.:ext))', - :controller => 'repositories', - :format => false, - :constraints => { - :action => /(browse|show|entry|raw|annotate|diff)/, - :rev => /[a-z0-9\.\-_]+/ - } - - get 'projects/:id/repository/statistics', :to => 'repositories#stats' - get 'projects/:id/repository/graph', :to => 'repositories#graph' - - get 'projects/:id/repository/changes(/*path(.:ext))', :to => 'repositories#changes' - - get 'projects/:id/repository/revisions', :to => 'repositories#revisions' - get 'projects/:id/repository/revisions/:rev', :to => 'repositories#revision' - get 'projects/:id/repository/revision', :to => 'repositories#revision' - post 'projects/:id/repository/revisions/:rev/issues', :to => 'repositories#add_related_issue' - delete 'projects/:id/repository/revisions/:rev/issues/:issue_id', :to => 'repositories#remove_related_issue' - get 'projects/:id/repository/revisions/:rev/:action(/*path(.:ext))', - :controller => 'repositories', - :format => false, - :constraints => { - :action => /(browse|show|entry|raw|annotate|diff)/, - :rev => /[a-z0-9\.\-_]+/ - } - get 'projects/:id/repository/:repository_id/:action(/*path(.:ext))', - :controller => 'repositories', - :action => /(browse|show|entry|raw|changes|annotate|diff)/ - get 'projects/:id/repository/:action(/*path(.:ext))', - :controller => 'repositories', - :action => /(browse|show|entry|raw|changes|annotate|diff)/ - - get 'projects/:id/repository/:repository_id', :to => 'repositories#show', :path => nil - get 'projects/:id/repository', :to => 'repositories#show', :path => nil - - # additional routes for having the file name at the end of url - - resources :groups do - member do - get 'autocomplete_for_user' - end - end - - match 'groups/:id/users', :controller => 'groups', :action => 'add_users', :id => /\d+/, :via => :post, :as => 'group_users' - match 'groups/:id/users/:user_id', :controller => 'groups', :action => 'remove_user', :id => /\d+/, :via => :delete, :as => 'group_user' - match 'groups/destroy_membership/:id', :controller => 'groups', :action => 'destroy_membership', :id => /\d+/, :via => :post - match 'groups/edit_membership/:id', :controller => 'groups', :action => 'edit_membership', :id => /\d+/, :via => :post - - resources :trackers, :except => :show do - collection do - match 'fields', :via => [:get, :post] - end - end - resources :issue_statuses, :except => :show do - collection do - post 'update_issue_done_ratio' - end - end - resources :custom_fields, :except => :show - resources :roles do - collection do - match 'permissions', :via => [:get, :post] - end - end - resources :enumerations, :except => :show - match 'enumerations/:type', :to => 'enumerations#index', :via => :get - - get 'projects/:id/search', :controller => 'search', :action => 'index' - get 'search', :controller => 'search', :action => 'index' - - match 'mail_handler', :controller => 'mail_handler', :action => 'index', :via => :post - - match 'admin', :controller => 'admin', :action => 'index', :via => :get - match 'admin/projects', :controller => 'admin', :action => 'projects', :via => :get - match 'admin/users', :controller => 'admin', :action => 'users', :via => :get - match 'admin/plugins', :controller => 'admin', :action => 'plugins', :via => :get - match 'admin/info', :controller => 'admin', :action => 'info', :via => :get - match 'admin/test_email', :controller => 'admin', :action => 'test_email', :via => :get - match 'admin/default_configuration', :controller => 'admin', :action => 'default_configuration', :via => :post - - resources :auth_sources do - member do - get 'test_connection', :as => 'try_connection' - end - collection do - get 'autocomplete_for_new_user' - end - end - - match 'workflows', :controller => 'workflows', :action => 'index', :via => :get - match 'workflows/edit', :controller => 'workflows', :action => 'edit', :via => [:get, :post] - match 'workflows/permissions', :controller => 'workflows', :action => 'permissions', :via => [:get, :post] - match 'workflows/copy', :controller => 'workflows', :action => 'copy', :via => [:get, :post] - match 'settings', :controller => 'settings', :action => 'index', :via => :get - match 'settings/edit', :controller => 'settings', :action => 'edit', :via => [:get, :post] - match 'settings/plugin/:id', :controller => 'settings', :action => 'plugin', :via => [:get, :post], :as => 'plugin_settings' - - match 'sys/projects', :to => 'sys#projects', :via => :get - match 'sys/projects/:id/repository', :to => 'sys#create_project_repository', :via => :post - match 'sys/fetch_changesets', :to => 'sys#fetch_changesets', :via => :get - - # Added by Tao - match 'upload_avatar', :to => 'avatar#upload', :via => :post - # Endof Tao's code - get 'robots.txt', :to => 'welcome#robots' - - ##############测试留言功能 fq - post 'words/new', :to => 'words#new' - post 'words/create', :to => 'words#create' - post 'words/append', :to => 'words#append' - post 'words/create_reply', :to => 'words#create_reply' - delete 'words/destroy', :to => 'words#destroy' - get 'words/more', :to => 'words#more' - get 'words/back', :to=> 'words#back' - ############## fq - post 'calls/create', :to => 'bids#create' - delete 'calls/destroy', :to => 'bids#destroy' - match 'calls/new', :controller => 'bids', :action => 'new', :via => [:get , :post] - get 'calls/more', :to => 'bids#more' - get 'calls/back', :to=> 'bids#back' - match 'calls/new_bid', :controller => 'bids', :action => 'new_bid' - match 'contest/new_contest', :controller => 'bids', :action => 'new_contest' #huang - match 'calls/:id/show_project', :controller => 'bids', :action => 'show_project', :as => 'project_for_bid' - match 'calls/:id/new_homework', :controller => 'homework_attach', :action => 'new', :as => 'new_homework_attach' - match 'calls/:id/add', :controller => 'bids', :action => 'add' - match 'calls/:id/delete', :controller => 'bids', :action => 'delete' - match 'calls/:id/add_homework', :controller => 'bids', :action => 'add_homework', via: :post - match 'calls/:id/new_submit_homework', to: 'bids#new_submit_homework', via: :get, as: 'new_submit_homework' - match 'words/add_project_respond', :controller => 'words', :action => 'add_project_respond' - match 'words/:id/leave_project_message', :controller => 'words', :action => 'leave_project_message' - - match 'projects/:id/feedback', :to => 'projects#feedback', :via => :get, :as => 'project_feedback' - match 'calls/create_bid', :to => 'bids#create_bid' - match 'contest/create_contest', :to => 'bids#create_contest' #huang - match 'calls/create_homework', :to => 'bids#create_homework' - match 'calls/:id/homework_respond', :to => 'bids#homework_respond' - match 'calls/:id/homework_statistics', :to => 'bids#homework_statistics' - match 'calls/:id/fork', :to => 'bids#fork', :as => 'fork' - match 'calls/:id/create_fork', :to => 'bids#create_fork' - match 'project/enterprise_course', :to => 'projects#enterprise_course' - match 'project/course_enterprise', :to => 'projects#course_enterprise' - match 'calls/:id/show_course', :to => 'bids#show_course', :as => 'show_course' - match 'calls/:id/show_bid_project', :to => 'bids#show_bid_project', :as => 'show_bid_project' - match 'calls/:id/show_bid_user', :to => 'bids#show_bid_user', :as => 'show_bid_user' - - match 'project/:id/share', :to => 'projects#share', :as => 'share_show' #share - - post 'join_in/join', :to => 'courses#join', :as => 'join' - delete 'join_in/join', :to => 'courses#unjoin' - post 'calls/:id/join_in_contest', :to => 'bids#join_in_contest', :as => 'join_in_contest' - delete 'calls/:id/join_in_contest', :to => 'bids#unjoin_in_contest' - match 'calls/:id/show_participator', :to => 'bids#show_participator' #bai - match 'calls/:id/update_contest', :to => 'bids#update_contest' #bai - match 'calls/:id/settings', :to => 'bids#settings' #bai - - match 'new_join', :to => 'projects#new_join', :as => 'try_join' - match 'new_join_in_contest', :to => 'bids#new_join', :as => 'try_join_in_contest' - match 'projects/:id/respond', :to => 'projects#project_respond', :via => :post - match 'calls/:id/manage',:to => 'bids#manage',:via => [:get,:post] - match 'project/course', :to => 'projects#course', :as => 'course' - - #added by william - # match 'calls/:id/set_results',:controller => 'bids', :action => 'set_results',:via => [:get,:post],:as => 'set_results' - # match 'calls/:id/set_prizes',:controller => 'bids',:action => 'set_prizes',:as => 'set_prizes' - match 'calls/:id/set_reward',:controller => 'bids',:action => 'set_reward',:as => 'set_reward' - - # added by young - match 'calls', :controller => 'bids', :action => 'index' - - match 'calls/:id', :controller => 'bids', :action => 'show', :as => 'respond' - match 'contest', :controller => 'bids', :action => 'contests', :as => 'contest' #modified @20140403 - - ######################## - ##added by wen########## - #######confusing######## - get 'welcome/search', to: 'welcome#search' - get 'school/index', to: 'school#index' - get 'course/:school_id', to: 'welcome#course' - get 'course/:school_id', to: 'welcome#course' - post 'school/get_options/:province', :to => 'school#get_options' - get 'school/get_options/:province', :to => 'school#get_options' - - post 'school/get_province', :to => 'school#get_province' - get 'school/get_province', :to => 'school#get_province' - - post 'school/get_schoollist/:province', :to => 'school#get_schoollist' - get 'school/get_schoollist/:province', :to => 'school#get_schoollist' - - post 'school/search_school/', :to => 'school#search_school' - get 'school/search_school/', :to => 'school#search_school' - - post 'school/upload', :to => 'school#upload' - - ######added by nie - match 'tags/show_projects_tags',:to => 'tags#show_projects_tags' - ########### added by liuping - match 'tags/add_tag',:to => 'tags#add_tag',:as=>"add_tag" - match 'tags/delete_tag',:to => 'tags#delete_tag',:as=>"add_tag" - match 'tags/show_all',:to => 'tags#show_all' - match 'parise_tread/praise_plus',:to => 'parise_tread#praise_plus',:as=>"praise" - match 'parise_tread/tread_plus',:to => 'parise_tread#tread_plus',:as=>"tread" - match 'tags/delete',:to=>'tags#delete' - match 'tags/remove_tag',:to=>'tags#remove_tag',:as=>"remove_tag" - match 'tags/tag_save', :as => "save_tag" - - match 'words/add_brief_introdution', :controller => 'words', :action => 'add_brief_introdution' - - - Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir| - file = File.join(plugin_dir, "config/routes.rb") - if File.exists?(file) - begin - instance_eval File.read(file) - rescue Exception => e - puts "An error occurred while loading the routes definition of #{File.basename(plugin_dir)} plugin (#{file}): #{e.message}." - exit 1 - end - end - end -end diff --git a/trustie2/config/settings.yml b/trustie2/config/settings.yml deleted file mode 100644 index 03f34399c..000000000 --- a/trustie2/config/settings.yml +++ /dev/null @@ -1,229 +0,0 @@ -# Redmine - project management software -# Copyright (C) 2006-2013 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. - - -# DO NOT MODIFY THIS FILE !!! -# Settings can be defined through the application in Admin -> Settings - -app_title: - default: 开源软件趋势分析 -app_subtitle: - default: Project management -welcome_text: - default: -login_required: - default: 0 -self_registration: - default: 3 -lost_password: - default: 1 -unsubscribe: - default: 1 -password_min_length: - format: int - default: 6 -# Maximum lifetime of user sessions in minutes -session_lifetime: - format: int - default: 525600 -# User session timeout in minutes -session_timeout: - format: int - default: 2880 -issues_export_limit: - format: int - default: 500 -activity_days_default: - format: int - default: 30 -per_page_options: - default: '25,50,100' -mail_from: - default: trustieforge@gmail.com -bcc_recipients: - default: 1 -plain_text_mail: - default: 0 -text_formatting: - default: textile -cache_formatted_text: - default: 0 -wiki_compression: - default: "" -default_language: - default: zh -host_name: - default: forge.trustie.net -protocol: - default: http -feeds_limit: - format: int - default: 15 -# Maximum size of files that can be displayed -# inline through the file viewer (in KB) -file_max_size_displayed: - format: int - default: 5120 -diff_max_lines_displayed: - format: int - default: 1500 -enabled_scm: - serialized: true - default: - - Git -autofetch_changesets: - default: 1 -sys_api_enabled: - default: 0 -sys_api_key: - default: '' -commit_cross_project_ref: - default: 0 -commit_ref_keywords: - default: 'refs,references,IssueID' -commit_fix_keywords: - default: 'fixes,closes' -commit_fix_status_id: - format: int - default: 0 -commit_fix_done_ratio: - default: 100 -commit_logtime_enabled: - default: 0 -commit_logtime_activity_id: - format: int - default: 0 -# autologin duration in days -# 0 means autologin is disabled -autologin: - format: int - default: 365 -# date format -date_format: - default: '' -time_format: - default: '' -user_format: - default: :firstname_lastname - format: symbol -cross_project_issue_relations: - default: 0 -# Enables subtasks to be in other projects -cross_project_subtasks: - default: 'tree' -issue_group_assignment: - default: 0 -default_issue_start_date_to_creation_date: - default: 1 -notified_events: - serialized: true - default: - - issue_added - - issue_updated -mail_handler_body_delimiters: - default: '' -mail_handler_api_enabled: - default: 0 -mail_handler_api_key: - default: -issue_list_default_columns: - serialized: true - default: - - tracker - - status - - priority - - title - - assigned_to - - updated_on -display_subprojects_issues: - default: 1 -issue_done_ratio: - default: 'issue_field' -default_projects_public: - default: 1 -default_projects_tracker_ids: - serialized: true - default: -# Role given to a non-admin user who creates a project -new_project_user_role_id: - format: int - default: 3 -sequential_project_identifiers: - default: 0 -# encodings used to convert repository files content to UTF-8 -# multiple values accepted, comma separated -repositories_encodings: - default: 'UTF-8' -# encoding used to convert commit logs to UTF-8 -commit_logs_encoding: - default: 'UTF-8' -repository_log_display_limit: - format: int - default: 100 -ui_theme: - default: 'redpenny-master' -emails_footer: - default: |- - You have received this notification because you have either subscribed to it, or are involved in it. - To change your notification preferences, please click here: http://hostname/my/account -gravatar_enabled: - default: 0 -openid: - default: 0 -gravatar_default: - default: '' -start_of_week: - default: '' -rest_api_enabled: - default: 0 -jsonp_enabled: - default: 0 -default_notification_option: - default: 'only_my_events' -emails_header: - default: '' -thumbnails_enabled: - default: 0 -thumbnails_size: - format: int - default: 100 -non_working_week_days: - serialized: true - default: - - '6' - - '7' -#### added by liuping -show_tags_length: - format: int - default: 5 -tags_min_length: - format: int - default: 1 -tags_max_length: - format: int - default: 30 -tags_show_search_results: - format: int - default: 5 -user_domain: - default: user.trustie.net -project_domain: - default: forge.trustie.net -contest_domain: - default: contest.trustie.net -course_domain: - default: course.trustie.net diff --git a/trustie2/config/sunspot.yml.example b/trustie2/config/sunspot.yml.example deleted file mode 100644 index ccb2085ae..000000000 --- a/trustie2/config/sunspot.yml.example +++ /dev/null @@ -1,23 +0,0 @@ -production: -# solr: -# hostname: localhost -# port: 8983 -# log_level: WARNING -# path: /solr/production -# # read_timeout: 2 -# # open_timeout: 0.5 -# -#development: -# solr: -# hostname: localhost -# port: 8982 -# log_level: INFO -# path: /solr/development -# -#test: -# solr: -# hostname: localhost -# port: 8981 -# log_level: WARNING -# path: /solr/test -# \ No newline at end of file diff --git a/trustie2/db/.DS_Store b/trustie2/db/.DS_Store deleted file mode 100644 index 699325fba..000000000 Binary files a/trustie2/db/.DS_Store and /dev/null differ diff --git a/trustie2/db/development.sqlite3 b/trustie2/db/development.sqlite3 deleted file mode 100644 index e69de29bb..000000000 diff --git a/trustie2/db/migrate/20170104044317_truncate_match_result_table.rb b/trustie2/db/migrate/20170104044317_truncate_match_result_table.rb deleted file mode 100644 index a0061d72b..000000000 --- a/trustie2/db/migrate/20170104044317_truncate_match_result_table.rb +++ /dev/null @@ -1,10 +0,0 @@ -class TruncateMatchResultTable < ActiveRecord::Migration - def change - arr = (1..70).to_a - arr.each do |letter| - #truncate_table "relative_memo_to_open_source_projects_#{letter}".to_sym - table_name = "relative_memo_to_open_source_projects_#{letter}".to_sym - ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{table_name}") - end - end -end diff --git a/trustie2/doc/CHANGELOG b/trustie2/doc/CHANGELOG deleted file mode 100644 index 3b472111b..000000000 --- a/trustie2/doc/CHANGELOG +++ /dev/null @@ -1,2451 +0,0 @@ -== Redmine changelog - -Redmine - project management software -Copyright (C) 2006-2013 Jean-Philippe Lang -http://www.redmine.org/ - -== 2013-05-01 v2.3.1 - -* Defect #12650: Lost text after selection in issue list with IE -* Defect #12684: Hotkey for Issue-Edit doesn't work as expected -* Defect #13405: Commit link title is escaped twice when using "commit:" prefix -* Defect #13541: Can't access SCM when log/production.scm.stderr.log is not writable -* Defect #13579: Datepicker uses Simplified Chinese in Traditional Chinese locale -* Defect #13584: Missing Portuguese jQuery UI date picker -* Defect #13586: Circular loop testing prevents precedes/follows relation between subtasks -* Defect #13618: CSV export of spent time ignores filters and columns selection -* Defect #13630: PDF export generates the issue id twice -* Defect #13644: Diff - Internal Error -* Defect #13712: Fix email rake tasks to also support no_account_notice and default_group options -* Defect #13811: Broken javascript in IE7 ; recurrence of #12195 -* Defect #13823: Trailing comma in javascript files -* Patch #13531: Traditional Chinese translation for 2.3-stable -* Patch #13552: Dutch translations for 2.3-stable -* Patch #13678: Lithuanian translation for 2.3-stable - -== 2013-03-19 v2.3.0 - -* Defect #3107: Issue with two digit year on Logtime -* Defect #3371: Autologin does not work when using openid -* Defect #3676: www. generates broken link in formatted text -* Defect #4700: Adding news does not send notification to all project members -* Defect #5329: Time entries report broken on first week of year -* Defect #8794: Circular loop when using relations and subtasks -* Defect #9475: German Translation "My custom queries" and "Custom queries" -* Defect #9549: Only 100 users are displayed when adding new project members -* Defect #10277: Redmine wikitext URL-into-link creation with hyphen is wrong -* Defect #10364: Custom field float separator in CSV export -* Defect #10930: rake redmine:load_default_data error in 2.0 with SQLServer -* Defect #10977: Redmine shouldn't require all database gems -* Defect #12528: Handle temporary failures gracefully in the external mail handler script -* Defect #12629: Wrong German "label_issues_by" translation -* Defect #12641: Diff outputs become ??? in some non ASCII words. -* Defect #12707: Typo in app/models/tracker.rb -* Defect #12716: Attachment description lost when issue validation fails -* Defect #12735: Negative duration allowed -* Defect #12736: Negative start/due dates allowed -* Defect #12968: Subtasks don't resepect following/precedes -* Defect #13006: Filter "Assignee's group" doesn't work with group assignments -* Defect #13022: Image pointing towards /logout signs out user -* Defect #13059: Custom fields are listed two times in workflow/Fields permission -* Defect #13076: Project overview page shows trackers from subprojects with disabled issue module -* Defect #13119: custom_field_values are not reloaded on #reload -* Defect #13154: After upgrade to 2.2.2 ticket list on some projects fails -* Defect #13188: Forms are not updated after changing the status field without "Add issues" permission -* Defect #13251: Adding a "follows" relation may not refresh relations list -* Defect #13272: translation missing: setting_default_projects_tracker_ids -* Defect #13328: Copying an issue as a child of itself creates an extra issue -* Defect #13335: Autologin does not work with custom autologin cookie name -* Defect #13350: Japanese mistranslation fix -* Feature #824: Add "closed_on" issue field (storing time of last closing) & add it as a column and filter on the issue list. -* Feature #1766: Custom fields should become addable to Spent Time list/report -* Feature #3436: Show relations in Gantt diagram -* Feature #3957: Ajax file upload with progress bar -* Feature #5298: Store attachments in sub directories -* Feature #5605: Subprojects should (optionally) inherit Members from their parent -* Feature #6727: Add/remove issue watchers via REST API -* Feature #7159: Bulk watch/unwatch issues from the context menu -* Feature #8529: Get the API key of the user through REST API -* Feature #8579: Multiple file upload with HTML5 / Drag-and-Drop -* Feature #10191: Add Filters For Spent time's Details and Report -* Feature #10286: Auto-populate fields while creating a new user with LDAP -* Feature #10352: Preview should already display the freshly attached images -* Feature #11498: Add --no-account-notice option for the mail handler script -* Feature #12122: Gantt progress lines (html only) -* Feature #12228: JRuby 1.7.2 support -* Feature #12251: Custom fields: 'Multiple values' should be able to be checked and then unchecked -* Feature #12401: Split "Manage documents" permission into create, edit and delete permissions -* Feature #12542: Group events in the activity view -* Feature #12665: Link to a file in a repository branch -* Feature #12713: Microsoft SQLServer support -* Feature #12787: Remove "Warning - iconv will be deprecated in the future, use String#encode instead." -* Feature #12843: Add links to projects in Group projects list -* Feature #12898: Handle GET /issues/context_menu parameters nicely to prevent returning error 500 to crawlers -* Feature #12992: Make JSONP support optional and disabled by default -* Feature #13174: Raise group name maximum length to 255 characters -* Feature #13175: Possibility to define the default enable trackers when creating a project -* Feature #13329: Ruby 2.0 support -* Feature #13337: Split translation "label_total" -* Feature #13340: Mail handler: option to add created user to default group -* Feature #13341: Mail handler: --no-notification option to disable notifications to the created user -* Patch #7202: Polish translation for v1.0.4 -* Patch #7851: Italian translation for 'issue' -* Patch #9225: Generate project identifier automatically with JavaScript -* Patch #10916: Optimisation in issues relations display -* Patch #12485: Don't force english language for default admin account -* Patch #12499: Use lambda in model scopes -* Patch #12611: Login link unexpected logs you out -* Patch #12626: Updated Japanese translations for button_view and permission_commit_access -* Patch #12640: Russian "about_x_hours" translation change -* Patch #12645: Russian numeric translation -* Patch #12660: Consistent German translation for my page -* Patch #12708: Restructured german translation (Cleanup) -* Patch #12721: Optimize MenuManager a bit -* Patch #12725: Change pourcent to percent (#12724) -* Patch #12754: Updated Japanese translation for notice_account_register_done -* Patch #12788: Copyright for 2013 -* Patch #12806: Serbian translation change -* Patch #12810: Swedish Translation change -* Patch #12910: Plugin settings div should perhaps have 'settings' CSS class -* Patch #12911: Fix 500 error for requests to the settings path for non-configurable plugins -* Patch #12926: Bulgarian translation (r11218) -* Patch #12927: Swedish Translation for r11244 -* Patch #12967: Change Spanish login/logout translations -* Patch #12988: Russian translation for trunk -* Patch #13080: German translation of label_in -* Patch #13098: Small datepicker improvements -* Patch #13152: Locale file for Azerbaijanian language -* Patch #13155: Add login to /users/:id API for current user -* Patch #13173: Put source :rubygems url HTTP secure -* Patch #13190: Bulgarian translation (r11404) -* Patch #13198: Traditional Chinese language file (to r11426) -* Patch #13203: German translation change for follow and precedes is inconsitent -* Patch #13206: Portuguese translation file -* Patch #13246: Some german translation patches -* Patch #13280: German translation (r11478) -* Patch #13301: Performance: avoid querying all memberships in User#roles_for_project -* Patch #13309: Add "tracker-[id]" CSS class to issues -* Patch #13324: fixing some pt-br locales -* Patch #13339: Complete language Vietnamese file -* Patch #13391: Czech translation update -* Patch #13399: Fixed some wrong or confusing translation in Korean locale -* Patch #13414: Bulgarian translation (r11567) -* Patch #13420: Korean translation for 2.3 (r11583) -* Patch #13437: German translation of setting_emails_header -* Patch #13438: English translation -* Patch #13447: German translation - some patches -* Patch #13450: Czech translation -* Patch #13475: fixing some pt-br locales -* Patch #13514: fixing some pt-br locales - -== 2013-03-19 v2.2.4 - -* Upgrade to Rails 3.2.13 -* Defect #12243: Ordering forum replies by last reply date is broken -* Defect #13127: h1 multiple lined titles breaks into main menu -* Defect #13138: Generating PDF of issue causes UndefinedConversionError with htmlentities gem -* Defect #13165: rdm-mailhandler.rb: initialize_http_header override basic auth -* Defect #13232: Link to topic in nonexistent forum causes error 500 -* Patch #13181: Bulgarian translation of jstoolbar-bg.js -* Patch #13207: Portuguese translation for 2.2-stable -* Patch #13310: pt-BR label_last_n_weeks translation -* Patch #13325: pt-BR translation for 2.2-stable -* Patch #13343: Vietnamese translation for 2.2-stable -* Patch #13398: Czech translation for 2.2-stable - -== 2013-02-12 v2.2.3 - -* Upgrade to Rails 3.2.12 -* Defect #11987: pdf: Broken new line in table -* Defect #12930: 404 Error when referencing different project source files in the wiki syntax -* Defect #12979: Wiki link syntax commit:repo_a:abcd doesn't work -* Defect #13075: Can't clear custom field value through context menu in the issue list -* Defect #13097: Project copy fails when wiki module is disabled -* Defect #13126: Issue view: estimated time vs. spent time -* Patch #12922: Update Spanish translation -* Patch #12928: Bulgarian translation for 2.2-stable -* Patch #12987: Russian translation for 2.2-stable - -== 2013-01-20 v2.2.2 - -* Defect #7510: Link to attachment should return latest attachment -* Defect #9842: {{toc}} is not replaced by table of content when exporting wiki page to pdf -* Defect #12749: Plugins cannot route wiki page sub-path -* Defect #12799: Cannot edit a wiki section which title starts with a tab -* Defect #12801: Viewing the history of a wiki page with attachments raises an error -* Defect #12833: Input fields restricted on length should have maxlength parameter set -* Defect #12838: Blank page when clicking Add with no block selected on my page layout -* Defect #12851: "Parent task is invalid" while editing child issues by Role with restricted Issues Visibility -* Patch #12800: Serbian Latin translation patch (sr-YU.yml) -* Patch #12809: Swedish Translation for r11162 -* Patch #12818: Minor swedish translation fix - -== 2013-01-09 v2.2.1 - -* Upgrade to Rails 3.2.11 -* Defect #12652: "Copy ticket" selects "new ticket" -* Defect #12691: Textile Homepage Dead? -* Defect #12711: incorrect fix of lib/SVG/Graph/TimeSeries.rb -* Defect #12744: Unable to call a macro with a name that contains uppercase letters -* Defect #12776: Security vulnerability in Rails 3.2.10 (CVE-2013-0156) -* Patch #12630: Russian "x_hours" translation - -== 2012-12-18 v2.2.0 - -* Defect #4787: Gannt to PNG - CJK (Chinese, Japanese and Korean) characters appear as ? -* Defect #8106: Issues by Category should show tasks without category -* Defect #8373: i18n string text_are_you_sure_with_children no longer used -* Defect #11426: Filtering with Due Date in less than N days should show overdue issues -* Defect #11834: Bazaar: "???" instead of non ASCII character in paths on non UTF-8 locale -* Defect #11868: Git and Mercurial diff displays deleted files as /dev/null -* Defect #11979: No validation errors when entering an invalid "Parent task" -* Defect #12012: Redmine::VERSION.revision method does not work on Subversion 1.7 working copy -* Defect #12018: Issue filter select box order changes randomly -* Defect #12090: email recipients not written to action_mailer log if BCC recipients setting is checked -* Defect #12092: Issue "start date" validation does not work correctly -* Defect #12285: Some unit and functional tests miss fixtures and break when run alone -* Defect #12286: Emails of private notes are sent to watcher users regardless of viewing permissions -* Defect #12310: Attachments may not be displayed in the order they were selected -* Defect #12356: Issue "Update" link broken focus -* Defect #12397: Error in Textile conversion of HTTP links, containing russian letters -* Defect #12434: Respond with 404 instead of 500 when requesting a wiki diff with invalid versions -* Feature #1554: Private comments in tickets -* Feature #2161: Time tracking code should respect weekends as "no work" days -* Feature #3239: Show related issues on the Issues Listing -* Feature #3265: Filter on issue relations -* Feature #3447: Option to display the issue descriptions on the issues list -* Feature #3511: Ability to sort issues by grouped column -* Feature #4590: Precede-Follow relation should move following issues when rescheduling issue earlier -* Feature #5487: Allow subtasks to cross projects -* Feature #6899: Add a relation between the original and copied issue -* Feature #7082: Rest API for wiki -* Feature #9835: REST API - List priorities -* Feature #10789: Macros {{child_pages}} with depth parameter -* Feature #10852: Ability to delete a version from a wiki page history -* Feature #10937: new user format #{lastname} -* Feature #11502: Expose roles details via REST API -* Feature #11755: Impersonate user through REST API auth -* Feature #12085: New user name format: firstname + first letter of lastname -* Feature #12125: Set filename used to store attachment updloaded via the REST API -* Feature #12167: Macro for inserting collapsible block of text -* Feature #12211: Wrap issue description and its contextual menu in a div -* Feature #12216: Textual CSS class for priorities -* Feature #12299: Redmine version requirement improvements (in plugins) -* Feature #12393: Upgrade to Rails 3.2.9 -* Feature #12475: Lazy loading of translation files for faster startup -* Patch #11846: Fill username when authentification failed -* Patch #11862: Add "last 2 weeks" preset to time entries reporting -* Patch #11992: Japanese translation about issue relations improved -* Patch #12027: Incorrect Spanish "September" month name -* Patch #12061: Japanese translation improvement (permission names) -* Patch #12078: User#allowed_to? should return true or false -* Patch #12117: Change Japanese translation of "admin" -* Patch #12142: Updated translation in Lithuanian -* Patch #12232: German translation enhancements -* Patch #12316: Fix Lithuanian numeral translation -* Patch #12494: Bulgarian "button_submit" translation change -* Patch #12514: Updated translation in Lithuanian -* Patch #12602: Korean translation update for 2.2-stable -* Patch #12608: Norwegian translation changed -* Patch #12619: Russian translation change - -== 2012-12-18 v2.1.5 - -* Defect #12400: Validation fails when receiving an email with list custom fields -* Defect #12451: Macros.rb extract_macro_options should use lazy search -* Defect #12513: Grouping of issues by custom fields not correct in PDF export -* Defect #12566: Issue history notes previews are broken -* Defect #12568: Clicking "edit" on a journal multiple times shows multiple forms -* Patch #12605: Norwegian translation for 1.4-stable update -* Patch #12614: Dutch translation -* Patch #12615: Russian translation - -== 2012-11-24 v2.1.4 - -* Defect #12274: Wiki export from Index by title is truncated -* Defect #12298: Right-click context menu unable to batch/bulk update (IE8) -* Defect #12332: Repository identifier does not display on Project/Settings/Repositories -* Defect #12396: Error when receiving an email without title header -* Defect #12399: Non ASCII attachment filename encoding broken (MOJIBAKE) in receiving mail on Ruby 1.8 -* Defect #12409: Git: changesets aren't read after clear_changesets call -* Defect #12431: Project.rebuild! sorts root projects by id instead of name - -== 2012-11-17 v2.1.3 - -* Defect #12050: :export links to repository files lead to a 404 error -* Defect #12189: Missing tmp/pdf directory -* Defect #12195: Javascript error with IE7 / IE8 on new issue form -* Defect #12196: "Page not found" on OK button in SCM "View all revisions" page -* Defect #12199: Confirmation message displayed when clicking a disabled delete link in the context menu -* Defect #12231: Hardcoded "Back" in Repository -* Defect #12294: Incorrect german translation for "registered" users filter -* Defect #12349: Watchers auto-complete search on non-latin chars -* Defect #12358: 'None' grouped issue list section should be translated -* Defect #12359: Version date field regex validation accepts invalid date -* Defect #12375: Receiving mail title encoding broken (MOJIBAKE) in some cases on Ruby 1.8 -* Patch #9732: German translations -* Patch #12021: Russian locale translations -* Patch #12188: Simplified Chinese translation with zh.yml file based on Rev:10681 -* Patch #12235: German translation for 2.1-stable -* Patch #12237: Added German Translation - -== 2012-09-30 v2.1.2 - -* Defect #11929: XSS vulnerability in Redmine 2.1.x - -== 2012-09-30 v2.1.1 - -* Defect #11290: ParseDate missing in Ruby 1.9x -* Defect #11844: "load_default_data" rake task fails to print the error message if one occurs -* Defect #11850: Can't create a user from ldap by on-the-fly on the redmine server using URI prefix -* Defect #11872: Private issue visible to anonymous users after its author is deleted -* Defect #11885: Filter misses Selectionfield on IE8 -* Defect #11893: New relation form Cancel link is broken with Chrome 21 -* Defect #11905: Potential "can't dup NilClass" error in UserPreference -* Defect #11909: Autocomplete results not reset after clearing search field -* Defect #11922: bs.yml and de.yml lead to error by number_to_currency() -* Defect #11945: rake task prints "can't convert Errno::EACCES into String" in case of no permission of public/plugin_assets -* Defect #11975: Undefined status transitions allowed in workflow (author of issue changes when selecting a new status) -* Defect #11982: SCM diff view generates extra parameter for switching mode -* Patch #11897: Traditional Chinese language file (to r10433) - -== 2012-09-16 v2.1.0 - -* Defect #2071: Reordering priority-enumerations breaks alternate-theme's issue-colouring -* Defect #2190: Month names not translated to german -* Defect #8978: LDAP timeout if an LDAP auth provider is unreachable -* Defect #9839: Gantt abbr of weekday should not be necessarily the first letter of the long day name -* Defect #10928: Documentation about generating a plugin is not up-to-date -* Defect #11034: TLS configuration documentation for Rails 3 -* Defect #11073: UserCustomField order_statement returns wrong output -* Defect #11153: Default sorting for target version is DESC instead of ASC -* Defect #11207: Issues associated with a locked version are not copied when copying a project -* Defect #11304: Issue-class: status-1, status-2 etc. refer to status position instead of status id -* Defect #11331: Openid registration form should not require user to enter password -* Defect #11345: Context menu should show shared versions when editing issues from different projects -* Defect #11355: Plain text notification emails content is HTML escaped -* Defect #11388: Updating a version through rest API returns invalid JSON -* Defect #11389: Warning in awesome_nested_set.rb -* Defect #11503: Accessing /projects/:project/wiki/something.png fails with error 500 -* Defect #11506: Versions that are not shared should not be assignable when selecting another project -* Defect #11508: Projects not ordered alphabetically after renaming project -* Defect #11540: Roadmap anchor links can be ambigous -* Defect #11545: Overwriting existing method Issue.open -* Defect #11552: MailHandler does not match assignee name with spaces -* Defect #11571: Custom fields of type version not proper handled in receiving e-mails -* Defect #11577: Can't use non-latin anchor in wiki -* Defect #11612: Revision graph sometimes broken due to raphael.js error -* Defect #11621: Redmine MIME Detection Of Javascript Files Non-Standard -* Defect #11633: Macro arguments should not be parsed by text formatters -* Defect #11662: Invalid query returned from Issues.visible scope after accessing User#projects_by_role with a role that is not present -* Defect #11691: 404 response when deleting a user from the edit page -* Defect #11723: redmine:send_reminders notification misses if assignee is a group -* Defect #11738: Batch update of issues clears project path -* Defect #11749: Redmine.pm: HEAD is not considered as a read-only method -* Defect #11814: Date picker does not respect week start setting -* Feature #703: Configurable required fields per tracker/status/role -* Feature #1006: Display thumbnails of attached images -* Feature #1091: Disabling default ticket fields per tracker -* Feature #1360: Permission for adding an issue to a version. -* Feature #3061: Let macros optionally match over multiple lines and ignore single curly braces -* Feature #3510: Inserting image thumbnails inside the wiki -* Feature #3521: Permissions for roles to change fields per tracker/status -* Feature #3640: Freeze / Close Projects -* Feature #3831: Support for subforums -* Feature #6597: Configurable session lifetime and timeout -* Feature #6965: Option to Copy Subtasks when copying an issue -* Feature #8161: Ability to filter issues on project custom fields -* Feature #8577: "Private" column and filter on the issue list -* Feature #8981: REST Api for Groups -* Feature #9258: Create role by copy -* Feature #9419: Group/sort the issue list by user/version-format custom fields -* Feature #10362: Show images in repositories inline when clicking the 'View' link -* Feature #10419: Upgrade raphael.js (2.1.0) -* Feature #11068: Ability to set default column order in issue list -* Feature #11102: Add autocomplete to "Related issue" field on revision -* Feature #11109: Repository Identifier should be frozen -* Feature #11181: Additional "Log time" link on project overview -* Feature #11205: Reversed order of priorities on the issue summary page -* Feature #11445: Switch from Prototype to JQuery -* Feature #11469: JSONP support -* Feature #11475: Redmine.pm: Allow fallback to other Apache auth providers -* Feature #11494: Don't turn #nnn with leading zeros into links -* Feature #11539: Display a projects tree instead of a flat list in notification preferences -* Feature #11578: Option to pass whole arguments to a macro without splitting them -* Feature #11595: Missing mime type for svg files -* Feature #11758: Upgrade to Rails 3.2.8 -* Patch #4905: Redmine.pm: add support for Git's smart HTTP protocol -* Patch #10988: New Korean translation patch -* Patch #11201: Korean translation special update -* Patch #11401: Fix Japanese mistranslation for "button_submit" -* Patch #11402: Japanese translation added for default role names -* Patch #11411: Fix disordered use of long sound in Japanese "user" translation -* Patch #11412: Unnatural Japanese message when users failed to login -* Patch #11419: Fix wrong Japanese "label_attachment" translation -* Patch #11496: Make labels clickable in Adminstration/Settings -* Patch #11704: Avoid the use of tag("...", "...", true) in layout -* Patch #11818: Redmine.pm fails when permissions are NULL - -== 2012-09-16 v2.0.4 - -* Defect #10818: Running rake in test environment causes exception -* Defect #11209: Wiki diff may generate broken HTML -* Defect #11217: Project names in drop-down are escaped twice -* Defect #11262: Link is escaped in wiki added/updated notification email -* Defect #11307: Can't filter for negative numeric custom fields -* Defect #11325: Unified diff link broken on specific file/revision diff view -* Defect #11341: Escaped link in conflict resolution form -* Defect #11365: Attachment description length is not validated -* Defect #11511: Confirmation page has broken HTML when a project folding sub project is deleted -* Defect #11533: rake redmine:plugins:test doesn't run tests in subdirectories -* Defect #11541: Version sharing is missing in the REST API -* Defect #11550: Issue reminder doesn't work when using asynchronous delivery -* Defect #11776: Can't override mailer views inside redmine plugin. -* Defect #11789: Edit section links broken with h5/h6 headings -* Feature #11338: Exclude emails with auto-submitted => auto-generated -* Patch #11299: redmine:plugins:migrate should update db/schema.rb -* Patch #11328: Fix Japanese mistranslation for 'label_language_based' -* Patch #11448: Russian translation for 1.4-stable and 2.0-stable -* Patch #11600: Fix plural form of the abbreviation for hours in Brazilian Portuguese - -== 2012-06-18 v2.0.3 - -* Defect #10688: PDF export from Wiki - Problems with tables -* Defect #11061: Cannot choose commit versions to view differences in Git/Mercurial repository view -* Defect #11065: E-Mail submitted tickets: German umlauts in 'title' get malformed (ruby 1.8) -* Defect #11098: Default priorities have the same position and can't be reordered -* Defect #11105: <% content_for :header_tags do %> doesn't work inside hook -* Defect #11112: REST API - custom fields in POST/PUT ignored for time_entries -* Defect #11118: "Maximum file size" displayed on upload forms is incorrect -* Defect #11124: Link to user is escaped in activity title -* Defect #11133: Wiki-page section edit link can point to incorrect section -* Defect #11160: SQL Error on time report if a custom field has multiple values for an entry -* Defect #11170: Topics sort order is broken in Redmine 2.x -* Defect #11178: Spent time sorted by date-descending order lists same-date entries in physical order (not-reverse) -* Defect #11185: Redmine fails to delete a project with parent/child task -* Feature #11162: Upgrade to Rails 3.2.6 -* Patch #11113: Small glitch in German localization - -== 2012-06-05 v2.0.2 - -* Defect #11032: Project list is not shown when "For any event on the selected projects only..." is selected on user edit panel -* Defect #11038: "Create and continue" should preserve project, issue and activity when logging time -* Defect #11046: Redmine.pm does not support "bind as user" ldap authentication -* Defect #11051: reposman.rb fails in 1.4.2 because of missing require for rubygems -* Defect #11085: Wiki start page can't be changed -* Feature #11084: Update Rails to 3.2.5 - -== 2012-05-28 v2.0.1 - -* Defect #10923: After creating a new Version Redmine jumps back to "Information" -* Defect #10932: Links to delete watchers are escaped when gravatars are enabled -* Defect #10964: Updated column doesn't get updated on issues -* Defect #10965: rake yard does not work for generating documentation. -* Defect #10972: Columns selection not displayed on the custom query form -* Defect #10991: My page > Spent time 'project' column is html-encoded -* Defect #10996: Time zones lost when upgrading from Redmine 1.4 to 2.0 -* Defect #11013: Fetching Email from IMAP/POP3 - uninitialized constant RAILS_DEFAULT_LOGGER error -* Defect #11024: redmine_plugin_model generator does not create the migration -* Defect #11027: Saving new query without name causes escaping of input field -* Defect #11028: Project identifier can be updated - -== 2012-05-15 v2.0.0 - -* Feature #4796: Rails 3 support -* Feature #7720: Limit the pagination-limit when max-results is fewer than max-pagination-limit -* Feature #9034: Add an id to the flash messages -* Patch #10782: Better translation for Estonian language - -== 2012-05-13 v1.4.2 - -* Defect #10744: rake task redmine:email:test broken -* Defect #10787: "Allow users to unsubscribe" option is confusing -* Defect #10827: Cannot access Repositories page and Settings in a Project - Error 500 -* Defect #10829: db:migrate fails 0.8.2 -> 1.4.1 -* Defect #10832: REST Uploads fail with fastcgi -* Defect #10837: reposman and rdm-mailhandler not working with ruby 1.9.x -* Defect #10856: can not load translations from hr.yml with ruby1.9.3-p194 -* Defect #10865: Filter reset when deleting locked user -* Feature #9790: Allow filtering text custom fields on "is null" and "is not null" -* Feature #10778: svn:ignore for config/additional_environment.rb -* Feature #10875: Partial Albanian Translations -* Feature #10888: Bring back List-Id to help aid Gmail filtering -* Patch #10733: Traditional Chinese language file (to r9502) -* Patch #10745: Japanese translation update (r9519) -* Patch #10750: Swedish Translation for r9522 -* Patch #10785: Bulgarian translation (jstoolbar) -* Patch #10800: Simplified Chinese translation - -== 2012-04-20 v1.4.1 - -* Defect #8574: Time report: date range fields not enabled when using the calendar popup -* Defect #10642: Nested textile ol/ul lists generate invalid HTML -* Defect #10668: RSS key is generated twice when user is not reloaded -* Defect #10669: Token.destroy_expired should not delete API tokens -* Defect #10675: "Submit and continue" is broken -* Defect #10711: User cannot change account details with "Login has already been taken" error -* Feature #10664: Unsubscribe Own User Account -* Patch #10693: German Translation Update - -== 2012-04-14 v1.4.0 - -* Defect #2719: Increase username length limit from 30 to 60 -* Defect #3087: Revision referring to issues across all projects -* Defect #4824: Unable to connect (can't convert Net::LDAP::LdapError into String) -* Defect #5058: reminder mails are not sent when delivery_method is :async_smtp -* Defect #6859: Moving issues to a tracker with different custom fields should let fill these fields -* Defect #7398: Error when trying to quick create a version with required custom field -* Defect #7495: Python multiline comments highlighting problem in Repository browser -* Defect #7826: bigdecimal-segfault-fix.rb must be removed for Oracle -* Defect #7920: Attempted to update a stale object when copying a project -* Defect #8857: Git: Too long in fetching repositories after upgrade from 1.1 or new branch at first time -* Defect #9472: The git scm module causes an excess amount of DB traffic. -* Defect #9685: Adding multiple times the same related issue relation is possible -* Defect #9798: Release 1.3.0 does not detect rubytree under ruby 1.9.3p0 / rails 2.3.14 -* Defect #9978: Japanese "permission_add_issue_watchers" is wrong -* Defect #10006: Email reminders are sent for closed issues -* Defect #10150: CSV export and spent time: rounding issue -* Defect #10168: CSV export breaks custom columns -* Defect #10181: Issue context menu and bulk edit form show irrelevant statuses -* Defect #10198: message_id regex in pop3.rb only recognizes Message-ID header (not Message-Id) -* Defect #10251: Description diff link in note details is relative when received by email -* Defect #10272: Ruby 1.9.3: "incompatible character encoding" with LDAP auth -* Defect #10275: Message object not passed to wiki macros for head topic and in preview edit mode -* Defect #10334: Full name is not unquoted when creating users from emails -* Defect #10410: [Localization] Grammar issue of Simplified Chinese in zh.yml -* Defect #10442: Ruby 1.9.3 Time Zone setting Internal error. -* Defect #10467: Confusing behavior while moving issue to a project with disabled Issues module -* Defect #10575: Uploading of attachments which filename contains non-ASCII chars fails with Ruby 1.9 -* Defect #10590: WikiContent::Version#text return string with #
with long strings may hang server
-* Defect #7337: My page french translation
-* Defect #7348: French Translation of "Connection"
-* Defect #7385: Error when viewing an issue which was related to a deleted subtask
-* Defect #7386: NoMethodError on pdf export
-* Defect #7415: Darcs adapter recognizes new files as modified files above Darcs 2.4
-* Defect #7421: no email sent with 'Notifiy for any event on the selected projects only'
-* Feature #5344: Update to latest CodeRay 0.9.x
-
-== 2011-01-09 v1.1.0
-
-* Defect #2038: Italics in wiki headers show-up wrong in the toc
-* Defect #3449: Redmine Takes Too Long On Large Mercurial Repository
-* Defect #3567: Sorting for changesets might go wrong on Mercurial repos
-* Defect #3707: {{toc}} doesn't work with {{include}}
-* Defect #5096: Redmine hangs up while browsing Git repository
-* Defect #6000: Safe Attributes prevents plugin extension of Issue model...
-* Defect #6064: Modules not assigned to projects created via API
-* Defect #6110: MailHandler should allow updating Issue Priority and Custom fields
-* Defect #6136: JSON API holds less information than XML API
-* Defect #6345: xml used by rest API is invalid
-* Defect #6348: Gantt chart PDF rendering errors
-* Defect #6403: Updating an issue with custom fields fails
-* Defect #6467: "Member of role", "Member of group" filter not work correctly
-* Defect #6473: New gantt broken after clearing issue filters
-* Defect #6541: Email notifications send to everybody
-* Defect #6549: Notification settings not migrated properly
-* Defect #6591: Acronyms must have a minimum of three characters
-* Defect #6674: Delete time log broken after changes to REST
-* Defect #6681: Mercurial, Bazaar and Darcs auto close issue text should be commit id instead of revision number
-* Defect #6724: Wiki uploads does not work anymore (SVN 4266)
-* Defect #6746: Wiki links are broken on Activity page
-* Defect #6747: Wiki diff does not work since r4265
-* Defect #6763: New gantt charts: title displayed twice on issues
-* Defect #6826: Clicking "Add" twice creates duplicate member record
-* Defect #6844: Unchecking status filter on the issue list has no effect
-* Defect #6895: Wrong Polish translation of "blocks"
-* Defect #6943: Migration from boolean to varchar fails on PostgreSQL 8.1
-* Defect #7064: Mercurial adapter does not recognize non alphabetic nor numeric in UTF-8 copied files
-* Defect #7128: New gantt chart does not render subtasks under parent task
-* Defect #7135: paging mechanism returns the same last page forever
-* Defect #7188: Activity page not refreshed when changing language
-* Defect #7195: Apply CLI-supplied defaults for incoming mail only to new issues not replies
-* Defect #7197: Tracker reset to default when replying to an issue email
-* Defect #7213: Copy project does not copy all roles and permissions
-* Defect #7225: Project settings: Trackers & Custom fields only relevant if module Issue tracking is active
-* Feature #630: Allow non-unique names for projects
-* Feature #1738: Add a "Visible" flag to project/user custom fields
-* Feature #2803: Support for Javascript in Themes
-* Feature #2852: Clean Incoming Email of quoted text "----- Reply above this line ------"
-* Feature #2995: Improve error message when trying to access an archived project
-* Feature #3170: Autocomplete issue relations on title
-* Feature #3503: Administrator Be Able To Modify Email settings Of Users
-* Feature #4155: Automatic spent time logging from commit messages
-* Feature #5136: Parent select on Wiki rename page
-* Feature #5338: Descendants (subtasks) should be available via REST API
-* Feature #5494: Wiki TOC should display heading from level 4
-* Feature #5594: Improve MailHandler's keyword handling
-* Feature #5622: Allow version to be set via incoming email
-* Feature #5712: Reload themes
-* Feature #5869: Issue filters by Group and Role
-* Feature #6092: Truncate Git revision labels in Activity page/feed and allow configurable length
-* Feature #6112: Accept localized keywords when receiving emails
-* Feature #6140: REST issues response with issue count limit and offset
-* Feature #6260: REST API for Users
-* Feature #6276: Gantt Chart rewrite
-* Feature #6446: Remove length limits on project identifier and name
-* Feature #6628: Improvements in truncate email
-* Feature #6779: Project JSON API
-* Feature #6823: REST API for time tracker.
-* Feature #7072: REST API for news
-* Feature #7111: Expose more detail on journal entries
-* Feature #7141: REST API: get information about current user
-* Patch #4807: Allow to set the done_ratio field with the incoming mail system
-* Patch #5441: Initialize TimeEntry attributes with params[:time_entry]
-* Patch #6762: Use GET instead of POST to retrieve context_menu
-* Patch #7160: French translation ofr "not_a_date" is missing
-* Patch #7212: Missing remove_index in AddUniqueIndexOnMembers down migration
-
-
-== 2010-12-23 v1.0.5
-
-* #6656: Mercurial adapter loses seconds of commit times
-* #6996: Migration trac(sqlite3) -> redmine(postgresql) doesnt escape ' char
-* #7013: v-1.0.4 trunk - see {{count}} in page display rather than value
-* #7016: redundant 'field_start_date' in ja.yml
-* #7018: 'undefined method `reschedule_after' for nil:NilClass' on new issues
-* #7024: E-mail notifications about Wiki changes.
-* #7033: 'class' attribute of tag shouldn't be truncate
-* #7035: CSV value separator in russian
-* #7122: Issue-description Quote-button missing
-* #7144: custom queries making use of deleted custom fields cause a 500 error
-* #7162: Multiply defined label in french translation
-
-== 2010-11-28 v1.0.4
-
-* #5324: Git not working if color.ui is enabled
-* #6447: Issues API doesn't allow full key auth for all actions
-* #6457: Edit User group problem
-* #6575: start date being filled with current date even when blank value is submitted
-* #6740: Max attachment size, incorrect usage of 'KB'
-* #6760: Select box sorted by ID instead of name in Issue Category
-* #6766: Changing target version name can cause an internal error
-* #6784: Redmine not working with i18n gem 0.4.2
-* #6839: Hardcoded absolute links in my/page_layout
-* #6841: Projects API doesn't allow full key auth for all actions
-* #6860: svn: Write error: Broken pipe when browsing repository
-* #6874: API should return XML description when creating a project
-* #6932: submitting wrong parent task input creates a 500 error
-* #6966: Records of Forums are remained, deleting project
-* #6990: Layout problem in workflow overview
-* #5117: mercurial_adapter should ensure the right LANG environment variable
-* #6782: Traditional Chinese language file (to r4352)
-* #6783: Swedish Translation for r4352
-* #6804: Bugfix: spelling fixes
-* #6814: Japanese Translation for r4362
-* #6948: Bulgarian translation
-* #6973: Update es.yml
-
-== 2010-10-31 v1.0.3
-
-* #4065: Redmine.pm doesn't work with LDAPS and a non-standard port
-* #4416: Link from version details page to edit the wiki.
-* #5484: Add new issue as subtask to an existing ticket
-* #5948: Update help/wiki_syntax_detailed.html with more link options
-* #6494: Typo in pt_BR translation for 1.0.2
-* #6508: Japanese translation update
-* #6509: Localization pt-PT (new strings)
-* #6511: Rake task to test email
-* #6525: Traditional Chinese language file (to r4225)
-* #6536: Patch for swedish translation
-* #6548: Rake tasks to add/remove i18n strings
-* #6569: Updated Hebrew translation
-* #6570: Japanese Translation for r4231
-* #6596: pt-BR translation updates
-* #6629: Change field-name of issues start date
-* #6669: Bulgarian translation
-* #6731: Macedonian translation fix
-* #6732: Japanese Translation for r4287
-* #6735: Add user-agent to reposman
-* #6736: Traditional Chinese language file (to r4288)
-* #6739: Swedish Translation for r4288
-* #6765: Traditional Chinese language file (to r4302)
-* Fixed #5324: Git not working if color.ui is enabled
-* Fixed #5652: Bad URL parsing in the wiki when it ends with right-angle-bracket(greater-than mark).
-* Fixed #5803: Precedes/Follows Relationships Broke
-* Fixed #6435: Links to wikipages bound to versions do not respect version-sharing in Settings -> Versions
-* Fixed #6438: Autologin cannot be disabled again once it's enabled
-* Fixed #6513: "Move" and "Copy" are not displayed when deployed in subdirectory
-* Fixed #6521: Tooltip/label for user "search-refinment" field on group/project member list
-* Fixed #6563: i18n-issues on calendar view
-* Fixed #6598: Wrong caption for button_create_and_continue in German language file
-* Fixed #6607: Unclear caption for german button_update
-* Fixed #6612: SortHelper missing from CalendarsController
-* Fixed #6740: Max attachment size, incorrect usage of 'KB'
-* Fixed #6750: ActionView::TemplateError (undefined method `empty?' for nil:NilClass) on line #12 of app/views/context_menus/issues.html.erb:
-
-== 2010-09-26 v1.0.2
-
-* #2285: issue-refinement: pressing enter should result to an "apply"
-* #3411: Allow mass status update trough context menu
-* #5929: https-enabled gravatars when called over https
-* #6189: Japanese Translation for r4011
-* #6197: Traditional Chinese language file (to r4036)
-* #6198: Updated german translation
-* #6208: Macedonian translation
-* #6210: Swedish Translation for r4039
-* #6248: nl translation update for r4050
-* #6263: Catalan translation update
-* #6275: After submitting a related issue, the Issue field should be re-focused
-* #6289: Checkboxes in issues list shouldn't be displayed when printing
-* #6290: Make journals theming easier
-* #6291: User#allowed_to? is not tested
-* #6306: Traditional Chinese language file (to r4061)
-* #6307: Korean translation update for 4066(4061)
-* #6316: pt_BR update
-* #6339: SERBIAN Updated
-* #6358: Updated Polish translation
-* #6363: Japanese Translation for r4080
-* #6365: Traditional Chinese language file (to r4081)
-* #6382: Issue PDF export variable usage
-* #6428: Interim solution for i18n >= 0.4
-* #6441: Japanese Translation for r4162
-* #6451: Traditional Chinese language file (to r4167)
-* #6465: Japanese Translation for r4171
-* #6466: Traditional Chinese language file (to r4171)
-* #6490: pt-BR translation for 1.0.2
-* Fixed #3935: stylesheet_link_tag with plugin doesn't take into account relative_url_root
-* Fixed #4998: Global issue list's context menu has enabled options for parent menus but there are no valid selections
-* Fixed #5170: Done ratio can not revert to 0% if status is used for done ratio
-* Fixed #5608: broken with i18n 0.4.0
-* Fixed #6054: Error 500 on filenames with whitespace in git reposities
-* Fixed #6135: Default logger configuration grows without bound.
-* Fixed #6191: Deletion of a main task deletes all subtasks
-* Fixed #6195: Missing move issues between projects
-* Fixed #6242: can't switch between inline and side-by-side diff
-* Fixed #6249: Create and continue returns 404
-* Fixed #6267: changing the authentication mode from ldap to internal with setting the password
-* Fixed #6270: diff coderay malformed in the "news" page
-* Fixed #6278: missing "cant_link_an_issue_with_a_descendant"from locale files
-* Fixed #6333: Create and continue results in a 404 Error
-* Fixed #6346: Age column on repository view is skewed for git, probably CVS too
-* Fixed #6351: Context menu on roadmap broken
-* Fixed #6388: New Subproject leads to a 404
-* Fixed #6392: Updated/Created links to activity broken
-* Fixed #6413: Error in SQL
-* Fixed #6443: Redirect to project settings after Copying a Project
-* Fixed #6448: Saving a wiki page with no content has a translation missing
-* Fixed #6452: Unhandled exception on creating File
-* Fixed #6471: Typo in label_report in Czech translation
-* Fixed #6479: Changing tracker type will lose watchers
-* Fixed #6499: Files with leading or trailing whitespace are not shown in git.
-
-== 2010-08-22 v1.0.1
-
-* #819: Add a body ID and class to all pages
-* #871: Commit new CSS styles!
-* #3301: Add favicon to base layout
-* #4656: On Issue#show page, clicking on “Add related issue� should focus on the input
-* #4896: Project identifier should be a limited field
-* #5084: Filter all isssues by projects
-* #5477: Replace Test::Unit::TestCase with ActiveSupport::TestCase
-* #5591: 'calendar' action is used with 'issue' controller in issue/sidebar
-* #5735: Traditional Chinese language file (to r3810)
-* #5740: Swedish Translation for r3810
-* #5785: pt-BR translation update
-* #5898: Projects should be displayed as links in users/memberships
-* #5910: Chinese translation to redmine-1.0.0
-* #5912: Translation update for french locale
-* #5962: Hungarian translation update to r3892
-* #5971: Remove falsly applied chrome on revision links
-* #5972: Updated Hebrew translation for 1.0.0
-* #5982: Updated german translation
-* #6008: Move admin_menu to Redmine::MenuManager
-* #6012: RTL layout
-* #6021: Spanish translation 1.0.0-RC
-* #6025: nl translation updated for r3905
-* #6030: Japanese Translation for r3907
-* #6074: sr-CY.yml contains DOS-type newlines (\r\n)
-* #6087: SERBIAN translation updated
-* #6093: Updated italian translation
-* #6142: Swedish Translation for r3940
-* #6153: Move view_calendar and view_gantt to own modules
-* #6169: Add issue status to issue tooltip
-* Fixed #3834: Add a warning when not choosing a member role
-* Fixed #3922: Bad english arround "Assigned to" text in journal entries
-* Fixed #5158: Simplified Chinese language file zh.yml updated to r3608
-* Fixed #5162: translation missing: zh-TW, field_time_entrie
-* Fixed #5297: openid not validated correctly
-* Fixed #5628: Wrong commit range in git log command
-* Fixed #5760: Assigned_to and author filters in "Projects>View all issues" should be based on user's project visibility
-* Fixed #5771: Problem when importing git repository
-* Fixed #5775: ldap authentication in admin menu should have an icon
-* Fixed #5811: deleting statuses doesnt delete workflow entries
-* Fixed #5834: Emails with trailing spaces incorrectly detected as invalid
-* Fixed #5846: ChangeChangesPathLengthLimit does not remove default for MySQL
-* Fixed #5861: Vertical scrollbar always visible in Wiki "code" blocks in Chrome.
-* Fixed #5883: correct label_project_latest Chinese translation
-* Fixed #5892: Changing status from contextual menu opens the ticket instead
-* Fixed #5904: Global gantt PDF and PNG should display project names
-* Fixed #5925: parent task's priority edit should be disabled through shortcut menu in issues list page
-* Fixed #5935: Add Another file to ticket doesn't work in IE Internet Explorer
-* Fixed #5937: Harmonize french locale "zero" translation with other locales
-* Fixed #5945: Forum message permalinks don't take pagination into account
-* Fixed #5978: Debug code still remains
-* Fixed #6009: When using "English (British)", the repository browser (svn) shows files over 1000 bytes as floating point (2.334355)
-* Fixed #6045: Repository file Diff view sometimes shows more than selected file
-* Fixed #6079: German Translation error in TimeEntryActivity
-* Fixed #6100: User's profile should display all visible projects
-* Fixed #6132: Allow Key based authentication in the Boards atom feed
-* Fixed #6163: Bad CSS class for calendar project menu_item
-* Fixed #6172: Browsing to a missing user's page shows the admin sidebar
-
-== 2010-07-18 v1.0.0 (Release candidate)
-
-* #443: Adds context menu to the roadmap issue lists
-* #443: Subtasking
-* #741: Description preview while editing an issue
-* #1131: Add support for alternate (non-LDAP) authentication
-* #1214: REST API for Issues
-* #1223: File upload on wiki edit form
-* #1755: add "blocked by" as a related issues option
-* #2420: Fetching emails from an POP server
-* #2482: Named scopes in Issue and ActsAsWatchable plus some view refactoring (logic extraction).
-* #2924: Make the right click menu more discoverable using a cursor property
-* #2985: Make syntax highlighting pluggable
-* #3201: Workflow Check/Uncheck All Rows/Columns
-* #3359: Update CodeRay 0.9
-* #3706: Allow assigned_to field configuration on Issue creation by email
-* #3936: configurable list of models to include in search
-* #4480: Create a link to the user profile from the administration interface
-* #4482: Cache textile rendering
-* #4572: Make it harder to ruin your database
-* #4573: Move github gems to Gemcutter
-* #4664: Add pagination to forum threads
-* #4732: Make login case-insensitive also for PostgreSQL
-* #4812: Create links to other projects
-* #4819: Replace images with smushed ones for speed
-* #4945: Allow custom fields attached to project to be searchable
-* #5121: Fix issues list layout overflow
-* #5169: Issue list view hook request
-* #5208: Aibility to edit wiki sidebar
-* #5281: Remove empty ul tags in the issue history
-* #5291: Updated basque translations
-* #5328: Automatically add "Repository" menu_item after repository creation
-* #5415: Fewer SQL statements generated for watcher_recipients
-* #5416: Exclude "fields_for" from overridden methods in TabularFormBuilder
-* #5573: Allow issue assignment in email
-* #5595: Allow start date and due dates to be set via incoming email
-* #5752: The projects view (/projects) renders ul's wrong
-* #5781: Allow to use more macros on the welcome page and project list
-* Fixed #1288: Unable to past escaped wiki syntax in an issue description
-* Fixed #1334: Wiki formatting character *_ and _*
-* Fixed #1416: Inline code with less-then/greater-than produces @lt; and @gt; respectively
-* Fixed #2473: Login and mail should not be case sensitive
-* Fixed #2990: Ruby 1.9 - wrong number of arguments (1 for 0) on rake db:migrate
-* Fixed #3089: Text formatting sometimes breaks when combined
-* Fixed #3690: Status change info duplicates on the issue screen
-* Fixed #3691: Redmine allows two files with the same file name to be uploaded to the same issue
-* Fixed #3764: ApplicationHelperTest fails with JRuby
-* Fixed #4265: Unclosed code tags in issue descriptions affects main UI
-* Fixed #4745: Bug in index.xml.builder (issues)
-* Fixed #4852: changing user/roles of project member not possible without javascript
-* Fixed #4857: Week number calculation in date picker is wrong if a week starts with Sunday
-* Fixed #4883: Bottom "contextual" placement in issue with associated changeset
-* Fixed #4918: Revisions r3453 and r3454 broke On-the-fly user creation with LDAP
-* Fixed #4935: Navigation to the Master Timesheet page (time_entries)
-* Fixed #5043: Flash messages are not displayed after the project settings[module/activity] saved
-* Fixed #5081: Broken links on public/help/wiki_syntax_detailed.html
-* Fixed #5104: Description of document not wikified on documents index
-* Fixed #5108: Issue linking fails inside of []s
-* Fixed #5199: diff code coloring using coderay
-* Fixed #5233: Add a hook to the issue report (Summary) view
-* Fixed #5265: timetracking: subtasks time is added to the main task
-* Fixed #5343: acts_as_event Doesn't Accept Outside URLs
-* Fixed #5440: UI Inconsistency : Administration > Enumerations table row headers should be enclosed in
-* Fixed #5463: 0.9.4 INSTALL and/or UPGRADE, missing session_store.rb
-* Fixed #5524: Update_parent_attributes doesn't work for the old parent issue when reparenting
-* Fixed #5548: SVN Repository: Can not list content of a folder which includes square brackets.
-* Fixed #5589: "with subproject" malfunction
-* Fixed #5676: Search for Numeric Value
-* Fixed #5696: Redmine + PostgreSQL 8.4.4 fails on _dir_list_content.rhtml
-* Fixed #5698: redmine:email:receive_imap fails silently for mails with title longer than 255 characters
-* Fixed #5700: TimelogController#destroy assumes success
-* Fixed #5751: developer role is mispelled
-* Fixed #5769: Popup Calendar doesn't Advance in Chrome
-* Fixed #5771: Problem when importing git repository
-* Fixed #5823: Error in comments in plugin.rb
-
-
-== 2010-07-07 v0.9.6
-
-* Fixed: Redmine.pm access by unauthorized users
-
-== 2010-06-24 v0.9.5
-
-* Linkify folder names on revision view
-* "fiters" and "options" should be hidden in print view via css
-* Fixed: NoMethodError when no issue params are submitted
-* Fixed: projects.atom with required authentication
-* Fixed: External links not correctly displayed in Wiki TOC
-* Fixed: Member role forms in project settings are not hidden after member added
-* Fixed: pre can't be inside p
-* Fixed: session cookie path does not respect RAILS_RELATIVE_URL_ROOT
-* Fixed: mail handler fails when the from address is empty
-
-
-== 2010-05-01 v0.9.4
-
-* Filters collapsed by default on issues index page for a saved query
-* Fixed: When categories list is too big the popup menu doesn't adjust (ex. in the issue list)
-* Fixed: remove "main-menu" div when the menu is empty
-* Fixed: Code syntax highlighting not working in Document page
-* Fixed: Git blame/annotate fails on moved files
-* Fixed: Failing test in test_show_atom
-* Fixed: Migrate from trac - not displayed Wikis
-* Fixed: Email notifications on file upload sent to empty recipient list
-* Fixed: Migrating from trac is not possible, fails to allocate memory
-* Fixed: Lost password no longer flashes a confirmation message
-* Fixed: Crash while deleting in-use enumeration
-* Fixed: Hard coded English string at the selection of issue watchers
-* Fixed: Bazaar v2.1.0 changed behaviour
-* Fixed: Roadmap display can raise an exception if no trackers are selected
-* Fixed: Gravatar breaks layout of "logged in" page
-* Fixed: Reposman.rb on Windows
-* Fixed: Possible error 500 while moving an issue to another project with SQLite
-* Fixed: backslashes in issue description/note should be escaped when quoted
-* Fixed: Long text in disrupts Associated revisions
-* Fixed: Links to missing wiki pages not red on project overview page
-* Fixed: Cannot delete a project with subprojects that shares versions
-* Fixed: Update of Subversion changesets broken under Solaris
-* Fixed: "Move issues" permission not working for Non member
-* Fixed: Sidebar overlap on Users tab of Group editor
-* Fixed: Error on db:migrate with table prefix set (hardcoded name in principal.rb)
-* Fixed: Report shows sub-projects for non-members
-* Fixed: 500 internal error when browsing any Redmine page in epiphany
-* Fixed: Watchers selection lost when issue creation fails
-* Fixed: When copying projects, redmine should not generate an email to people who created issues
-* Fixed: Issue "#" table cells should have a class attribute to enable fine-grained CSS theme
-* Fixed: Plugin generators should display help if no parameter is given
-
-
-== 2010-02-28 v0.9.3
-
-* Adds filter for system shared versions on the cross project issue list
-* Makes project identifiers searchable
-* Remove invalid utf8 sequences from commit comments and author name
-* Fixed: Wrong link when "http" not included in project "Homepage" link
-* Fixed: Escaping in html email templates
-* Fixed: Pound (#) followed by number with leading zero (0) removes leading zero when rendered in wiki
-* Fixed: Deselecting textile text formatting causes interning empty string errors
-* Fixed: error with postgres when entering a non-numeric id for an issue relation
-* Fixed: div.task incorrectly wrapping on Gantt Chart
-* Fixed: Project copy loses wiki pages hierarchy
-* Fixed: parent project field doesn't include blank value when a member with 'add subproject' permission edits a child project
-* Fixed: Repository.fetch_changesets tries to fetch changesets for archived projects
-* Fixed: Duplicated project name for subproject version on gantt chart
-* Fixed: roadmap shows subprojects issues even if subprojects is unchecked
-* Fixed: IndexError if all the :last menu items are deleted from a menu
-* Fixed: Very high CPU usage for a long time when fetching commits from a large Git repository
-
-
-== 2010-02-07 v0.9.2
-
-* Fixed: Sub-project repository commits not displayed on parent project issues
-* Fixed: Potential security leak on my page calendar
-* Fixed: Project tree structure is broken by deleting the project with the subproject
-* Fixed: Error message shown duplicated when creating a new group
-* Fixed: Firefox cuts off large pages
-* Fixed: Invalid format parameter returns a DoubleRenderError on issues index
-* Fixed: Unnecessary Quote button on locked forum message
-* Fixed: Error raised when trying to view the gantt or calendar with a grouped query
-* Fixed: PDF support for Korean locale
-* Fixed: Deprecation warning in extra/svn/reposman.rb
-
-
-== 2010-01-30 v0.9.1
-
-* Vertical alignment for inline images in formatted text set to 'middle'
-* Fixed: Redmine.pm error "closing dbh with active statement handles at /usr/lib/perl5/Apache/Redmine.pm"
-* Fixed: copyright year in footer set to 2010
-* Fixed: Trac migration script may not output query lines
-* Fixed: Email notifications may affect language of notice messages on the UI
-* Fixed: Can not search for 2 letters word
-* Fixed: Attachments get saved on issue update even if validation fails
-* Fixed: Tab's 'border-bottom' not absent when selected
-* Fixed: Issue summary tables that list by user are not sorted
-* Fixed: Issue pdf export fails if target version is set
-* Fixed: Issue list export to PDF breaks when issues are sorted by a custom field
-* Fixed: SQL error when adding a group
-* Fixes: Min password length during password reset always displays as 4 chars
-
-
-== 2010-01-09 v0.9.0 (Release candidate)
-
-* Unlimited subproject nesting
-* Multiple roles per user per project
-* User groups
-* Inheritence of versions
-* OpenID login
-* "Watched by me" issue filter
-* Project copy
-* Project creation by non admin users
-* Accept emails from anyone on a private project
-* Add email notification on Wiki changes
-* Make issue description non-required field
-* Custom fields for Versions
-* Being able to sort the issue list by custom fields
-* Ability to close versions
-* User display/editing of custom fields attached to their user profile
-* Add "follows" issue relation
-* Copy workflows between trackers and roles
-* Defaults enabled modules list for project creation
-* Weighted version completion percentage on the roadmap
-* Autocreate user account when user submits email that creates new issue
-* CSS class on overdue issues on the issue list
-* Enable tracker update on issue edit form
-* Remove issue watchers
-* Ability to move threads between project forums
-* Changed custom field "Possible values" to a textarea
-* Adds projects association on tracker form
-* Set session store to cookie store by default
-* Set a default wiki page on project creation
-* Roadmap for main project should see Roadmaps for sub projects
-* Ticket grouping on the issue list
-* Hierarchical Project links in the page header
-* Allow My Page blocks to be added to from a plugin
-* Sort issues by multiple columns
-* Filters of saved query are now visible and be adjusted without editing the query
-* Saving "sort order" in custom queries
-* Url to fetch changesets for a repository
-* Managers able to create subprojects
-* Issue Totals on My Page Modules
-* Convert Enumerations to single table inheritance (STI)
-* Allow custom my_page blocks to define drop-down names
-* "View Issues" user permission added
-* Ask user what to do with child pages when deleting a parent wiki page
-* Contextual quick search
-* Allow resending of password by email
-* Change reply title to be a link to the reply itself
-* Include Logged Time as part of the project's Activity history
-* REST API for authentication
-* Browse through Git branches
-* Setup Object Daddy to replace test fixtures
-* Setup shoulda to make it easier to test
-* Custom fields and overrides on Enumerations
-* Add or remove columns from the issue list
-* Ability to add new version from issues screen
-* Setting to choose which day calendars start
-* Asynchronous email delivery method
-* RESTful URLs for (almost) everything
-* Include issue status in search results and activity pages
-* Add email to admin user search filter
-* Proper content type for plain text mails
-* Default value of project jump box
-* Tree based menus
-* Ability to use issue status to update percent done
-* Second set of issue "Action Links" at the bottom of an issue page
-* Proper exist status code for rdm-mailhandler.rb
-* Remove incoming email body via a delimiter
-* Fixed: Custom querry 'Export to PDF' ignores field selection
-* Fixed: Related e-mail notifications aren't threaded
-* Fixed: No warning when the creation of a categories from the issue form fails
-* Fixed: Actually block issues from closing when relation 'blocked by' isn't closed
-* Fixed: Include both first and last name when sorting by users
-* Fixed: Table cell with multiple line text
-* Fixed: Project overview page shows disabled trackers
-* Fixed: Cross project issue relations and user permissions
-* Fixed: My page shows tickets the user doesn't have access to
-* Fixed: TOC does not parse wiki page reference links with description
-* Fixed: Target version-list on bulk edit form is incorrectly sorted
-* Fixed: Cannot modify/delete project named "Documents"
-* Fixed: Email address in brackets breaks html
-* Fixed: Timelog detail loose issue filter passing to report tab
-* Fixed: Inform about custom field's name maximum length
-* Fixed: Activity page and Atom feed links contain project id instead of identifier
-* Fixed: no Atom key for forums with only 1 forum
-* Fixed: When reading RSS feed in MS Outlook, the inline links are broken.
-* Fixed: Sometimes new posts don't show up in the topic list of a forum.
-* Fixed: The all/active filter selection in the project view does not stick.
-* Fixed: Login box has Different width
-* Fixed: User removed from project - still getting project update emails
-* Fixed: Project with the identifier of 'new' cannot be viewed
-* Fixed: Artefacts in search view (Cyrillic)
-* Fixed: Allow [#id] as title to reply by email
-* Fixed: Wrong language used when closing an issue via a commit message
-* Fixed: email handler drops emails for new issues with no title
-* Fixed: Calendar misspelled under Roles/Permissions
-* Fixed: Emails from no-reply redmine's address hell cycle
-* Fixed: child_pages macro fails on wiki page history
-* Fixed: Pre-filled time tracking date ignores timezone
-* Fixed: Links on locked users lead to 404 page
-* Fixed: Page changes in issue-list when using context menu
-* Fixed: diff parser removes lines starting with multiple dashes
-* Fixed: Quoting in forums resets message title
-* Fixed: Editing issue comment removes quote link
-* Fixed: Redmine.pm ignore browse_repository permission
-* Fixed: text formatting breaks on [msg1][msg2]
-* Fixed: Spent Time Default Value of 0.0
-* Fixed: Wiki pages in search results are referenced by project number, not by project identifier.
-* Fixed: When logging in via an autologin cookie the user's last_login_on should be updated
-* Fixed: 50k users cause problems in project->settings->members screen
-* Fixed: Document timestamp needs to show updated timestamps
-* Fixed: Users getting notifications for issues they are no longer allowed to view
-* Fixed: issue summary counts should link to the issue list without subprojects
-* Fixed: 'Delete' link on LDAP list has no effect
-
-
-== 2009-11-15 v0.8.7
-
-* Fixed: Hide paragraph terminator at the end of headings on html export
-* Fixed: pre tags containing " at the beginning of lines
-* Adds a Reply link to each issue note
-* Adds plain text only option for mail notifications
-* Gravatar support for issue detail, user grid, and activity stream (disabled by default)
-* Adds 'Delete wiki pages attachments' permission
-* Show the most recent file when displaying an inline image
-* Makes permission screens localized
-* AuthSource list: display associated users count and disable 'Delete' buton if any
-* Make the 'duplicates of' relation asymmetric
-* Adds username to the password reminder email
-* Adds links to forum messages using message#id syntax
-* Allow same name for custom fields on different object types
-* One-click bulk edition using the issue list context menu within the same project
-* Adds support for commit logs reencoding to UTF-8 before insertion in the database. Source encoding of commit logs can be selected in Application settings -> Repositories.
-* Adds checkboxes toggle links on permissions report
-* Adds Trac-Like anchors on wiki headings
-* Adds support for wiki links with anchor
-* Adds category to the issue context menu
-* Adds a workflow overview screen
-* Appends the filename to the attachment url so that clients that ignore content-disposition http header get the real filename
-* Dots allowed in custom field name
-* Adds posts quoting functionality
-* Adds an option to generate sequential project identifiers
-* Adds mailto link on the user administration list
-* Ability to remove enumerations (activities, priorities, document categories) that are in use. Associated objects can be reassigned to another value
-* Gantt chart: display issues that don't have a due date if they are assigned to a version with a date
-* Change projects homepage limit to 255 chars
-* Improved on-the-fly account creation. If some attributes are missing (eg. not present in the LDAP) or are invalid, the registration form is displayed so that the user is able to fill or fix these attributes
-* Adds "please select" to activity select box if no activity is set as default
-* Do not silently ignore timelog validation failure on issue edit
-* Adds a rake task to send reminder emails
-* Allow empty cells in wiki tables
-* Makes wiki text formatter pluggable
-* Adds back textile acronyms support
-* Remove pre tag attributes
-* Plugin hooks
-* Pluggable admin menu
-* Plugins can provide activity content
-* Moves plugin list to its own administration menu item
-* Adds url and author_url plugin attributes
-* Adds Plugin#requires_redmine method so that plugin compatibility can be checked against current Redmine version
-* Adds atom feed on time entries details
-* Adds project name to issues feed title
-* Adds a css class on menu items in order to apply item specific styles (eg. icons)
-* Adds a Redmine plugin generators
-* Adds timelog link to the issue context menu
-* Adds links to the user page on various views
-* Turkish translation by Ismail Sezen
-* Catalan translation
-* Vietnamese translation
-* Slovak translation
-* Better naming of activity feed if only one kind of event is displayed
-* Enable syntax highlight on issues, messages and news
-* Add target version to the issue list context menu
-* Hide 'Target version' filter if no version is defined
-* Add filters on cross-project issue list for custom fields marked as 'For all projects'
-* Turn ftp urls into links
-* Hiding the View Differences button when a wiki page's history only has one version
-* Messages on a Board can now be sorted by the number of replies
-* Adds a class ('me') to events of the activity view created by current user
-* Strip pre/code tags content from activity view events
-* Display issue notes in the activity view
-* Adds links to changesets atom feed on repository browser
-* Track project and tracker changes in issue history
-* Adds anchor to atom feed messages links
-* Adds a key in lang files to set the decimal separator (point or comma) in csv exports
-* Makes importer work with Trac 0.8.x
-* Upgraded to Prototype 1.6.0.1
-* File viewer for attached text files
-* Menu mapper: add support for :before, :after and :last options to #push method and add #delete method
-* Removed inconsistent revision numbers on diff view
-* CVS: add support for modules names with spaces
-* Log the user in after registration if account activation is not needed
-* Mercurial adapter improvements
-* Trac importer: read session_attribute table to find user's email and real name
-* Ability to disable unused SCM adapters in application settings
-* Adds Filesystem adapter
-* Clear changesets and changes with raw sql when deleting a repository for performance
-* Redmine.pm now uses the 'commit access' permission defined in Redmine
-* Reposman can create any type of scm (--scm option)
-* Reposman creates a repository if the 'repository' module is enabled at project level only
-* Display svn properties in the browser, svn >= 1.5.0 only
-* Reduces memory usage when importing large git repositories
-* Wider SVG graphs in repository stats
-* SubversionAdapter#entries performance improvement
-* SCM browser: ability to download raw unified diffs
-* More detailed error message in log when scm command fails
-* Adds support for file viewing with Darcs 2.0+
-* Check that git changeset is not in the database before creating it
-* Unified diff viewer for attached files with .patch or .diff extension
-* File size display with Bazaar repositories
-* Git adapter: use commit time instead of author time
-* Prettier url for changesets
-* Makes changes link to entries on the revision view
-* Adds a field on the repository view to browse at specific revision
-* Adds new projects atom feed
-* Added rake tasks to generate rcov code coverage reports
-* Add Redcloth's :block_markdown_rule to allow horizontal rules in wiki
-* Show the project hierarchy in the drop down list for new membership on user administration screen
-* Split user edit screen into tabs
-* Renames bundled RedCloth to RedCloth3 to avoid RedCloth 4 to be loaded instead
-* Fixed: Roadmap crashes when a version has a due date > 2037
-* Fixed: invalid effective date (eg. 99999-01-01) causes an error on version edition screen
-* Fixed: login filter providing incorrect back_url for Redmine installed in sub-directory
-* Fixed: logtime entry duplicated when edited from parent project
-* Fixed: wrong digest for text files under Windows
-* Fixed: associated revisions are displayed in wrong order on issue view
-* Fixed: Git Adapter date parsing ignores timezone
-* Fixed: Printing long roadmap doesn't split across pages
-* Fixes custom fields display order at several places
-* Fixed: urls containing @ are parsed as email adress by the wiki formatter
-* Fixed date filters accuracy with SQLite
-* Fixed: tokens not escaped in highlight_tokens regexp
-* Fixed Bazaar shared repository browsing
-* Fixes platform determination under JRuby
-* Fixed: Estimated time in issue's journal should be rounded to two decimals
-* Fixed: 'search titles only' box ignored after one search is done on titles only
-* Fixed: non-ASCII subversion path can't be displayed
-* Fixed: Inline images don't work if file name has upper case letters or if image is in BMP format
-* Fixed: document listing shows on "my page" when viewing documents is disabled for the role
-* Fixed: Latest news appear on the homepage for projects with the News module disabled
-* Fixed: cross-project issue list should not show issues of projects for which the issue tracking module was disabled
-* Fixed: the default status is lost when reordering issue statuses
-* Fixes error with Postgresql and non-UTF8 commit logs
-* Fixed: textile footnotes no longer work
-* Fixed: http links containing parentheses fail to reder correctly
-* Fixed: GitAdapter#get_rev should use current branch instead of hardwiring master
-
-
-== 2008-07-06 v0.7.3
-
-* Allow dot in firstnames and lastnames
-* Add project name to cross-project Atom feeds
-* Encoding set to utf8 in example database.yml
-* HTML titles on forums related views
-* Fixed: various XSS vulnerabilities
-* Fixed: Entourage (and some old client) fails to correctly render notification styles
-* Fixed: Fixed: timelog redirects inappropriately when :back_url is blank
-* Fixed: wrong relative paths to images in wiki_syntax.html
-
-
-== 2008-06-15 v0.7.2
-
-* "New Project" link on Projects page
-* Links to repository directories on the repo browser
-* Move status to front in Activity View
-* Remove edit step from Status context menu
-* Fixed: No way to do textile horizontal rule
-* Fixed: Repository: View differences doesn't work
-* Fixed: attachement's name maybe invalid.
-* Fixed: Error when creating a new issue
-* Fixed: NoMethodError on @available_filters.has_key?
-* Fixed: Check All / Uncheck All in Email Settings
-* Fixed: "View differences" of one file at /repositories/revision/ fails
-* Fixed: Column width in "my page"
-* Fixed: private subprojects are listed on Issues view
-* Fixed: Textile: bold, italics, underline, etc... not working after parentheses
-* Fixed: Update issue form: comment field from log time end out of screen
-* Fixed: Editing role: "issue can be assigned to this role" out of box
-* Fixed: Unable use angular braces after include word
-* Fixed: Using '*' as keyword for repository referencing keywords doesn't work
-* Fixed: Subversion repository "View differences" on each file rise ERROR
-* Fixed: View differences for individual file of a changeset fails if the repository URL doesn't point to the repository root
-* Fixed: It is possible to lock out the last admin account
-* Fixed: Wikis are viewable for anonymous users on public projects, despite not granting access
-* Fixed: Issue number display clipped on 'my issues'
-* Fixed: Roadmap version list links not carrying state
-* Fixed: Log Time fieldset in IssueController#edit doesn't set default Activity as default
-* Fixed: git's "get_rev" API should use repo's current branch instead of hardwiring "master"
-* Fixed: browser's language subcodes ignored
-* Fixed: Error on project selection with numeric (only) identifier.
-* Fixed: Link to PDF doesn't work after creating new issue
-* Fixed: "Replies" should not be shown on forum threads that are locked
-* Fixed: SVN errors lead to svn username/password being displayed to end users (security issue)
-* Fixed: http links containing hashes don't display correct
-* Fixed: Allow ampersands in Enumeration names
-* Fixed: Atom link on saved query does not include query_id
-* Fixed: Logtime info lost when there's an error updating an issue
-* Fixed: TOC does not parse colorization markups
-* Fixed: CVS: add support for modules names with spaces
-* Fixed: Bad rendering on projects/add
-* Fixed: exception when viewing differences on cvs
-* Fixed: export issue to pdf will messup when use Chinese language
-* Fixed: Redmine::Scm::Adapters::GitAdapter#get_rev ignored GIT_BIN constant
-* Fixed: Adding non-ASCII new issue type in the New Issue page have encoding error using IE
-* Fixed: Importing from trac : some wiki links are messed
-* Fixed: Incorrect weekend definition in Hebrew calendar locale
-* Fixed: Atom feeds don't provide author section for repository revisions
-* Fixed: In Activity views, changesets titles can be multiline while they should not
-* Fixed: Ignore unreadable subversion directories (read disabled using authz)
-* Fixed: lib/SVG/Graph/Graph.rb can't externalize stylesheets
-* Fixed: Close statement handler in Redmine.pm
-
-
-== 2008-05-04 v0.7.1
-
-* Thai translation added (Gampol Thitinilnithi)
-* Translations updates
-* Escape HTML comment tags
-* Prevent "can't convert nil into String" error when :sort_order param is not present
-* Fixed: Updating tickets add a time log with zero hours
-* Fixed: private subprojects names are revealed on the project overview
-* Fixed: Search for target version of "none" fails with postgres 8.3
-* Fixed: Home, Logout, Login links shouldn't be absolute links
-* Fixed: 'Latest projects' box on the welcome screen should be hidden if there are no projects
-* Fixed: error when using upcase language name in coderay
-* Fixed: error on Trac import when :due attribute is nil
-
-
-== 2008-04-28 v0.7.0
-
-* Forces Redmine to use rails 2.0.2 gem when vendor/rails is not present
-* Queries can be marked as 'For all projects'. Such queries will be available on all projects and on the global issue list.
-* Add predefined date ranges to the time report
-* Time report can be done at issue level
-* Various timelog report enhancements
-* Accept the following formats for "hours" field: 1h, 1 h, 1 hour, 2 hours, 30m, 30min, 1h30, 1h30m, 1:30
-* Display the context menu above and/or to the left of the click if needed
-* Make the admin project files list sortable
-* Mercurial: display working directory files sizes unless browsing a specific revision
-* Preserve status filter and page number when using lock/unlock/activate links on the users list
-* Redmine.pm support for LDAP authentication
-* Better error message and AR errors in log for failed LDAP on-the-fly user creation
-* Redirected user to where he is coming from after logging hours
-* Warn user that subprojects are also deleted when deleting a project
-* Include subprojects versions on calendar and gantt
-* Notify project members when a message is posted if they want to receive notifications
-* Fixed: Feed content limit setting has no effect
-* Fixed: Priorities not ordered when displayed as a filter in issue list
-* Fixed: can not display attached images inline in message replies
-* Fixed: Boards are not deleted when project is deleted
-* Fixed: trying to preview a new issue raises an exception with postgresql
-* Fixed: single file 'View difference' links do not work because of duplicate slashes in url
-* Fixed: inline image not displayed when including a wiki page
-* Fixed: CVS duplicate key violation
-* Fixed: ActiveRecord::StaleObjectError exception on closing a set of circular duplicate issues
-* Fixed: custom field filters behaviour
-* Fixed: Postgresql 8.3 compatibility
-* Fixed: Links to repository directories don't work
-
-
-== 2008-03-29 v0.7.0-rc1
-
-* Overall activity view and feed added, link is available on the project list
-* Git VCS support
-* Rails 2.0 sessions cookie store compatibility
-* Use project identifiers in urls instead of ids
-* Default configuration data can now be loaded from the administration screen
-* Administration settings screen split to tabs (email notifications options moved to 'Settings')
-* Project description is now unlimited and optional
-* Wiki annotate view
-* Escape HTML tag in textile content
-* Add Redmine links to documents, versions, attachments and repository files
-* New setting to specify how many objects should be displayed on paginated lists. There are 2 ways to select a set of issues on the issue list:
- * by using checkbox and/or the little pencil that will select/unselect all issues
- * by clicking on the rows (but not on the links), Ctrl and Shift keys can be used to select multiple issues
-* Context menu disabled on links so that the default context menu of the browser is displayed when right-clicking on a link (click anywhere else on the row to display the context menu)
-* User display format is now configurable in administration settings
-* Issue list now supports bulk edit/move/delete (for a set of issues that belong to the same project)
-* Merged 'change status', 'edit issue' and 'add note' actions:
- * Users with 'edit issues' permission can now update any property including custom fields when adding a note or changing the status
- * 'Change issue status' permission removed. To change an issue status, a user just needs to have either 'Edit' or 'Add note' permissions and some workflow transitions allowed
-* Details by assignees on issue summary view
-* 'New issue' link in the main menu (accesskey 7). The drop-down lists to add an issue on the project overview and the issue list are removed
-* Change status select box default to current status
-* Preview for issue notes, news and messages
-* Optional description for attachments
-* 'Fixed version' label changed to 'Target version'
-* Let the user choose when deleting issues with reported hours to:
- * delete the hours
- * assign the hours to the project
- * reassign the hours to another issue
-* Date range filter and pagination on time entries detail view
-* Propagate time tracking to the parent project
-* Switch added on the project activity view to include subprojects
-* Display total estimated and spent hours on the version detail view
-* Weekly time tracking block for 'My page'
-* Permissions to edit time entries
-* Include subprojects on the issue list, calendar, gantt and timelog by default (can be turned off is administration settings)
-* Roadmap enhancements (separate related issues from wiki contents, leading h1 in version wiki pages is hidden, smaller wiki headings)
-* Make versions with same date sorted by name
-* Allow issue list to be sorted by target version
-* Related changesets messages displayed on the issue details view
-* Create a journal and send an email when an issue is closed by commit
-* Add 'Author' to the available columns for the issue list
-* More appropriate default sort order on sortable columns
-* Add issue title to the time entries view and issue title, description and tracker to the csv export
-* Permissions to edit issue notes
-* Display date/time instead of date on files list
-* Do not show Roadmap menu item if the project doesn't define any versions
-* Allow longer version names (60 chars)
-* Ability to copy an existing workflow when creating a new role
-* Display custom fields in two columns on the issue form
-* Added 'estimated time' in the csv export of the issue list
-* Display the last 30 days on the activity view rather than the current month (number of days can be configured in the application settings)
-* Setting for whether new projects should be public by default
-* User preference to choose how comments/replies are displayed: in chronological or reverse chronological order
-* Added default value for custom fields
-* Added tabindex property on wiki toolbar buttons (to easily move from field to field using the tab key)
-* Redirect to issue page after creating a new issue
-* Wiki toolbar improvements (mainly for Firefox)
-* Display wiki syntax quick ref link on all wiki textareas
-* Display links to Atom feeds
-* Breadcrumb nav for the forums
-* Show replies when choosing to display messages in the activity
-* Added 'include' macro to include another wiki page
-* RedmineWikiFormatting page available as a static HTML file locally
-* Wrap diff content
-* Strip out email address from authors in repository screens
-* Highlight the current item of the main menu
-* Added simple syntax highlighters for php and java languages
-* Do not show empty diffs
-* Show explicit error message when the scm command failed (eg. when svn binary is not available)
-* Lithuanian translation added (Sergej Jegorov)
-* Ukrainan translation added (Natalia Konovka & Mykhaylo Sorochan)
-* Danish translation added (Mads Vestergaard)
-* Added i18n support to the jstoolbar and various settings screen
-* RedCloth's glyphs no longer user
-* New icons for the wiki toolbar (from http://www.famfamfam.com/lab/icons/silk/)
-* The following menus can now be extended by plugins: top_menu, account_menu, application_menu
-* Added a simple rake task to fetch changesets from the repositories: rake redmine:fetch_changesets
-* Remove hardcoded "Redmine" strings in account related emails and use application title instead
-* Mantis importer preserve bug ids
-* Trac importer: Trac guide wiki pages skipped
-* Trac importer: wiki attachments migration added
-* Trac importer: support database schema for Trac migration
-* Trac importer: support CamelCase links
-* Removes the Redmine version from the footer (can be viewed on admin -> info)
-* Rescue and display an error message when trying to delete a role that is in use
-* Add various 'X-Redmine' headers to email notifications: X-Redmine-Host, X-Redmine-Site, X-Redmine-Project, X-Redmine-Issue-Id, -Author, -Assignee, X-Redmine-Topic-Id
-* Add "--encoding utf8" option to the Mercurial "hg log" command in order to get utf8 encoded commit logs
-* Fixed: Gantt and calendar not properly refreshed (fragment caching removed)
-* Fixed: Textile image with style attribute cause internal server error
-* Fixed: wiki TOC not rendered properly when used in an issue or document description
-* Fixed: 'has already been taken' error message on username and email fields if left empty
-* Fixed: non-ascii attachement filename with IE
-* Fixed: wrong url for wiki syntax pop-up when Redmine urls are prefixed
-* Fixed: search for all words doesn't work
-* Fixed: Do not show sticky and locked checkboxes when replying to a message
-* Fixed: Mantis importer: do not duplicate Mantis username in firstname and lastname if realname is blank
-* Fixed: Date custom fields not displayed as specified in application settings
-* Fixed: titles not escaped in the activity view
-* Fixed: issue queries can not use custom fields marked as 'for all projects' in a project context
-* Fixed: on calendar, gantt and in the tracker filter on the issue list, only active trackers of the project (and its sub projects) should be available
-* Fixed: locked users should not receive email notifications
-* Fixed: custom field selection is not saved when unchecking them all on project settings
-* Fixed: can not lock a topic when creating it
-* Fixed: Incorrect filtering for unset values when using 'is not' filter
-* Fixed: PostgreSQL issues_seq_id not updated when using Trac importer
-* Fixed: ajax pagination does not scroll up
-* Fixed: error when uploading a file with no content-type specified by the browser
-* Fixed: wiki and changeset links not displayed when previewing issue description or notes
-* Fixed: 'LdapError: no bind result' error when authenticating
-* Fixed: 'LdapError: invalid binding information' when no username/password are set on the LDAP account
-* Fixed: CVS repository doesn't work if port is used in the url
-* Fixed: Email notifications: host name is missing in generated links
-* Fixed: Email notifications: referenced changesets, wiki pages, attachments... are not turned into links
-* Fixed: Do not clear issue relations when moving an issue to another project if cross-project issue relations are allowed
-* Fixed: "undefined method 'textilizable'" error on email notification when running Repository#fetch_changesets from the console
-* Fixed: Do not send an email with no recipient, cc or bcc
-* Fixed: fetch_changesets fails on commit comments that close 2 duplicates issues.
-* Fixed: Mercurial browsing under unix-like os and for directory depth > 2
-* Fixed: Wiki links with pipe can not be used in wiki tables
-* Fixed: migrate_from_trac doesn't import timestamps of wiki and tickets
-* Fixed: when bulk editing, setting "Assigned to" to "nobody" causes an sql error with Postgresql
-
-
-== 2008-03-12 v0.6.4
-
-* Fixed: private projects name are displayed on account/show even if the current user doesn't have access to these private projects
-* Fixed: potential LDAP authentication security flaw
-* Fixed: context submenus on the issue list don't show up with IE6.
-* Fixed: Themes are not applied with Rails 2.0
-* Fixed: crash when fetching Mercurial changesets if changeset[:files] is nil
-* Fixed: Mercurial repository browsing
-* Fixed: undefined local variable or method 'log' in CvsAdapter when a cvs command fails
-* Fixed: not null constraints not removed with Postgresql
-* Doctype set to transitional
-
-
-== 2007-12-18 v0.6.3
-
-* Fixed: upload doesn't work in 'Files' section
-
-
-== 2007-12-16 v0.6.2
-
-* Search engine: issue custom fields can now be searched
-* News comments are now textilized
-* Updated Japanese translation (Satoru Kurashiki)
-* Updated Chinese translation (Shortie Lo)
-* Fixed Rails 2.0 compatibility bugs:
- * Unable to create a wiki
- * Gantt and calendar error
- * Trac importer error (readonly? is defined by ActiveRecord)
-* Fixed: 'assigned to me' filter broken
-* Fixed: crash when validation fails on issue edition with no custom fields
-* Fixed: reposman "can't find group" error
-* Fixed: 'LDAP account password is too long' error when leaving the field empty on creation
-* Fixed: empty lines when displaying repository files with Windows style eol
-* Fixed: missing body closing tag in repository annotate and entry views
-
-
-== 2007-12-10 v0.6.1
-
-* Rails 2.0 compatibility
-* Custom fields can now be displayed as columns on the issue list
-* Added version details view (accessible from the roadmap)
-* Roadmap: more accurate completion percentage calculation (done ratio of open issues is now taken into account)
-* Added per-project tracker selection. Trackers can be selected on project settings
-* Anonymous users can now be allowed to create, edit, comment issues, comment news and post messages in the forums
-* Forums: messages can now be edited/deleted (explicit permissions need to be given)
-* Forums: topics can be locked so that no reply can be added
-* Forums: topics can be marked as sticky so that they always appear at the top of the list
-* Forums: attachments can now be added to replies
-* Added time zone support
-* Added a setting to choose the account activation strategy (available in application settings)
-* Added 'Classic' theme (inspired from the v0.51 design)
-* Added an alternate theme which provides issue list colorization based on issues priority
-* Added Bazaar SCM adapter
-* Added Annotate/Blame view in the repository browser (except for Darcs SCM)
-* Diff style (inline or side by side) automatically saved as a user preference
-* Added issues status changes on the activity view (by Cyril Mougel)
-* Added forums topics on the activity view (disabled by default)
-* Added an option on 'My account' for users who don't want to be notified of changes that they make
-* Trac importer now supports mysql and postgresql databases
-* Trac importer improvements (by Mat Trudel)
-* 'fixed version' field can now be displayed on the issue list
-* Added a couple of new formats for the 'date format' setting
-* Added Traditional Chinese translation (by Shortie Lo)
-* Added Russian translation (iGor kMeta)
-* Project name format limitation removed (name can now contain any character)
-* Project identifier maximum length changed from 12 to 20
-* Changed the maximum length of LDAP account to 255 characters
-* Removed the 12 characters limit on passwords
-* Added wiki macros support
-* Performance improvement on workflow setup screen
-* More detailed html title on several views
-* Custom fields can now be reordered
-* Search engine: search can be restricted to an exact phrase by using quotation marks
-* Added custom fields marked as 'For all projects' to the csv export of the cross project issue list
-* Email notifications are now sent as Blind carbon copy by default
-* Fixed: all members (including non active) should be deleted when deleting a project
-* Fixed: Error on wiki syntax link (accessible from wiki/edit)
-* Fixed: 'quick jump to a revision' form on the revisions list
-* Fixed: error on admin/info if there's more than 1 plugin installed
-* Fixed: svn or ldap password can be found in clear text in the html source in editing mode
-* Fixed: 'Assigned to' drop down list is not sorted
-* Fixed: 'View all issues' link doesn't work on issues/show
-* Fixed: error on account/register when validation fails
-* Fixed: Error when displaying the issue list if a float custom field is marked as 'used as filter'
-* Fixed: Mercurial adapter breaks on missing :files entry in changeset hash (James Britt)
-* Fixed: Wrong feed URLs on the home page
-* Fixed: Update of time entry fails when the issue has been moved to an other project
-* Fixed: Error when moving an issue without changing its tracker (Postgresql)
-* Fixed: Changes not recorded when using :pserver string (CVS adapter)
-* Fixed: admin should be able to move issues to any project
-* Fixed: adding an attachment is not possible when changing the status of an issue
-* Fixed: No mime-types in documents/files downloading
-* Fixed: error when sorting the messages if there's only one board for the project
-* Fixed: 'me' doesn't appear in the drop down filters on a project issue list.
-
-== 2007-11-04 v0.6.0
-
-* Permission model refactoring.
-* Permissions: there are now 2 builtin roles that can be used to specify permissions given to other users than members of projects
-* Permissions: some permissions (eg. browse the repository) can be removed for certain roles
-* Permissions: modules (eg. issue tracking, news, documents...) can be enabled/disabled at project level
-* Added Mantis and Trac importers
-* New application layout
-* Added "Bulk edit" functionality on the issue list
-* More flexible mail notifications settings at user level
-* Added AJAX based context menu on the project issue list that provide shortcuts for editing, re-assigning, changing the status or the priority, moving or deleting an issue
-* Added the hability to copy an issue. It can be done from the "issue/show" view or from the context menu on the issue list
-* Added the ability to customize issue list columns (at application level or for each saved query)
-* Overdue versions (date reached and open issues > 0) are now always displayed on the roadmap
-* Added the ability to rename wiki pages (specific permission required)
-* Search engines now supports pagination. Results are sorted in reverse chronological order
-* Added "Estimated hours" attribute on issues
-* A category with assigned issue can now be deleted. 2 options are proposed: remove assignments or reassign issues to another category
-* Forum notifications are now also sent to the authors of the thread, even if they don�t watch the board
-* Added an application setting to specify the application protocol (http or https) used to generate urls in emails
-* Gantt chart: now starts at the current month by default
-* Gantt chart: month count and zoom factor are automatically saved as user preferences
-* Wiki links can now refer to other project wikis
-* Added wiki index by date
-* Added preview on add/edit issue form
-* Emails footer can now be customized from the admin interface (Admin -> Email notifications)
-* Default encodings for repository files can now be set in application settings (used to convert files content and diff to UTF-8 so that they�re properly displayed)
-* Calendar: first day of week can now be set in lang files
-* Automatic closing of duplicate issues
-* Added a cross-project issue list
-* AJAXified the SCM browser (tree view)
-* Pretty URL for the repository browser (Cyril Mougel)
-* Search engine: added a checkbox to search titles only
-* Added "% done" in the filter list
-* Enumerations: values can now be reordered and a default value can be specified (eg. default issue priority)
-* Added some accesskeys
-* Added "Float" as a custom field format
-* Added basic Theme support
-* Added the ability to set the �done ratio� of issues fixed by commit (Nikolay Solakov)
-* Added custom fields in issue related mail notifications
-* Email notifications are now sent in plain text and html
-* Gantt chart can now be exported to a graphic file (png). This functionality is only available if RMagick is installed.
-* Added syntax highlightment for repository files and wiki
-* Improved automatic Redmine links
-* Added automatic table of content support on wiki pages
-* Added radio buttons on the documents list to sort documents by category, date, title or author
-* Added basic plugin support, with a sample plugin
-* Added a link to add a new category when creating or editing an issue
-* Added a "Assignable" boolean on the Role model. If unchecked, issues can not be assigned to users having this role.
-* Added an option to be able to relate issues in different projects
-* Added the ability to move issues (to another project) without changing their trackers.
-* Atom feeds added on project activity, news and changesets
-* Added the ability to reset its own RSS access key
-* Main project list now displays root projects with their subprojects
-* Added anchor links to issue notes
-* Added reposman Ruby version. This script can now register created repositories in Redmine (Nicolas Chuche)
-* Issue notes are now included in search
-* Added email sending test functionality
-* Added LDAPS support for LDAP authentication
-* Removed hard-coded URLs in mail templates
-* Subprojects are now grouped by projects in the navigation drop-down menu
-* Added a new value for date filters: this week
-* Added cache for application settings
-* Added Polish translation (Tomasz Gawryl)
-* Added Czech translation (Jan Kadlecek)
-* Added Romanian translation (Csongor Bartus)
-* Added Hebrew translation (Bob Builder)
-* Added Serbian translation (Dragan Matic)
-* Added Korean translation (Choi Jong Yoon)
-* Fixed: the link to delete issue relations is displayed even if the user is not authorized to delete relations
-* Performance improvement on calendar and gantt
-* Fixed: wiki preview doesn�t work on long entries
-* Fixed: queries with multiple custom fields return no result
-* Fixed: Can not authenticate user against LDAP if its DN contains non-ascii characters
-* Fixed: URL with ~ broken in wiki formatting
-* Fixed: some quotation marks are rendered as strange characters in pdf
-
-
-== 2007-07-15 v0.5.1
-
-* per project forums added
-* added the ability to archive projects
-* added �Watch� functionality on issues. It allows users to receive notifications about issue changes
-* custom fields for issues can now be used as filters on issue list
-* added per user custom queries
-* commit messages are now scanned for referenced or fixed issue IDs (keywords defined in Admin -> Settings)
-* projects list now shows the list of public projects and private projects for which the user is a member
-* versions can now be created with no date
-* added issue count details for versions on Reports view
-* added time report, by member/activity/tracker/version and year/month/week for the selected period
-* each category can now be associated to a user, so that new issues in that category are automatically assigned to that user
-* added autologin feature (disabled by default)
-* optimistic locking added for wiki edits
-* added wiki diff
-* added the ability to destroy wiki pages (requires permission)
-* a wiki page can now be attached to each version, and displayed on the roadmap
-* attachments can now be added to wiki pages (original patch by Pavol Murin) and displayed online
-* added an option to see all versions in the roadmap view (including completed ones)
-* added basic issue relations
-* added the ability to log time when changing an issue status
-* account information can now be sent to the user when creating an account
-* author and assignee of an issue always receive notifications (even if they turned of mail notifications)
-* added a quick search form in page header
-* added 'me' value for 'assigned to' and 'author' query filters
-* added a link on revision screen to see the entire diff for the revision
-* added last commit message for each entry in repository browser
-* added the ability to view a file diff with free to/from revision selection.
-* text files can now be viewed online when browsing the repository
-* added basic support for other SCM: CVS (Ralph Vater), Mercurial and Darcs
-* added fragment caching for svn diffs
-* added fragment caching for calendar and gantt views
-* login field automatically focused on login form
-* subproject name displayed on issue list, calendar and gantt
-* added an option to choose the date format: language based or ISO 8601
-* added a simple mail handler. It lets users add notes to an existing issue by replying to the initial notification email.
-* a 403 error page is now displayed (instead of a blank page) when trying to access a protected page
-* added portuguese translation (Joao Carlos Clementoni)
-* added partial online help japanese translation (Ken Date)
-* added bulgarian translation (Nikolay Solakov)
-* added dutch translation (Linda van den Brink)
-* added swedish translation (Thomas Habets)
-* italian translation update (Alessio Spadaro)
-* japanese translation update (Satoru Kurashiki)
-* fixed: error on history atom feed when there�s no notes on an issue change
-* fixed: error in journalizing an issue with longtext custom fields (Postgresql)
-* fixed: creation of Oracle schema
-* fixed: last day of the month not included in project activity
-* fixed: files with an apostrophe in their names can't be accessed in SVN repository
-* fixed: performance issue on RepositoriesController#revisions when a changeset has a great number of changes (eg. 100,000)
-* fixed: open/closed issue counts are always 0 on reports view (postgresql)
-* fixed: date query filters (wrong results and sql error with postgresql)
-* fixed: confidentiality issue on account/show (private project names displayed to anyone)
-* fixed: Long text custom fields displayed without line breaks
-* fixed: Error when editing the wokflow after deleting a status
-* fixed: SVN commit dates are now stored as local time
-
-
-== 2007-04-11 v0.5.0
-
-* added per project Wiki
-* added rss/atom feeds at project level (custom queries can be used as feeds)
-* added search engine (search in issues, news, commits, wiki pages, documents)
-* simple time tracking functionality added
-* added version due dates on calendar and gantt
-* added subprojects issue count on project Reports page
-* added the ability to copy an existing workflow when creating a new tracker
-* added the ability to include subprojects on calendar and gantt
-* added the ability to select trackers to display on calendar and gantt (Jeffrey Jones)
-* added side by side svn diff view (Cyril Mougel)
-* added back subproject filter on issue list
-* added permissions report in admin area
-* added a status filter on users list
-* support for password-protected SVN repositories
-* SVN commits are now stored in the database
-* added simple svn statistics SVG graphs
-* progress bars for roadmap versions (Nick Read)
-* issue history now shows file uploads and deletions
-* #id patterns are turned into links to issues in descriptions and commit messages
-* japanese translation added (Satoru Kurashiki)
-* chinese simplified translation added (Andy Wu)
-* italian translation added (Alessio Spadaro)
-* added scripts to manage SVN repositories creation and user access control using ssh+svn (Nicolas Chuche)
-* better calendar rendering time
-* fixed migration scripts to work with mysql 5 running in strict mode
-* fixed: error when clicking "add" with no block selected on my/page_layout
-* fixed: hard coded links in navigation bar
-* fixed: table_name pre/suffix support
-
-
-== 2007-02-18 v0.4.2
-
-* Rails 1.2 is now required
-* settings are now stored in the database and editable through the application in: Admin -> Settings (config_custom.rb is no longer used)
-* added project roadmap view
-* mail notifications added when a document, a file or an attachment is added
-* tooltips added on Gantt chart and calender to view the details of the issues
-* ability to set the sort order for roles, trackers, issue statuses
-* added missing fields to csv export: priority, start date, due date, done ratio
-* added total number of issues per tracker on project overview
-* all icons replaced (new icons are based on GPL icon set: "KDE Crystal Diamond 2.5" -by paolino- and "kNeu! Alpha v0.1" -by Pablo Fabregat-)
-* added back "fixed version" field on issue screen and in filters
-* project settings screen split in 4 tabs
-* custom fields screen split in 3 tabs (one for each kind of custom field)
-* multiple issues pdf export now rendered as a table
-* added a button on users/list to manually activate an account
-* added a setting option to disable "password lost" functionality
-* added a setting option to set max number of issues in csv/pdf exports
-* fixed: subprojects count is always 0 on projects list
-* fixed: locked users are proposed when adding a member to a project
-* fixed: setting an issue status as default status leads to an sql error with SQLite
-* fixed: unable to delete an issue status even if it's not used yet
-* fixed: filters ignored when exporting a predefined query to csv/pdf
-* fixed: crash when french "issue_edit" email notification is sent
-* fixed: hide mail preference not saved (my/account)
-* fixed: crash when a new user try to edit its "my page" layout
-
-
-== 2007-01-03 v0.4.1
-
-* fixed: emails have no recipient when one of the project members has notifications disabled
-
-
-== 2007-01-02 v0.4.0
-
-* simple SVN browser added (just needs svn binaries in PATH)
-* comments can now be added on news
-* "my page" is now customizable
-* more powerfull and savable filters for issues lists
-* improved issues change history
-* new functionality: move an issue to another project or tracker
-* new functionality: add a note to an issue
-* new report: project activity
-* "start date" and "% done" fields added on issues
-* project calendar added
-* gantt chart added (exportable to pdf)
-* single/multiple issues pdf export added
-* issues reports improvements
-* multiple file upload for issues, documents and files
-* option to set maximum size of uploaded files
-* textile formating of issue and news descritions (RedCloth required)
-* integration of DotClear jstoolbar for textile formatting
-* calendar date picker for date fields (LGPL DHTML Calendar http://sourceforge.net/projects/jscalendar)
-* new filter in issues list: Author
-* ajaxified paginators
-* news rss feed added
-* option to set number of results per page on issues list
-* localized csv separator (comma/semicolon)
-* csv output encoded to ISO-8859-1
-* user custom field displayed on account/show
-* default configuration improved (default roles, trackers, status, permissions and workflows)
-* language for default configuration data can now be chosen when running 'load_default_data' task
-* javascript added on custom field form to show/hide fields according to the format of custom field
-* fixed: custom fields not in csv exports
-* fixed: project settings now displayed according to user's permissions
-* fixed: application error when no version is selected on projects/add_file
-* fixed: public actions not authorized for members of non public projects
-* fixed: non public projects were shown on welcome screen even if current user is not a member
-
-
-== 2006-10-08 v0.3.0
-
-* user authentication against multiple LDAP (optional)
-* token based "lost password" functionality
-* user self-registration functionality (optional)
-* custom fields now available for issues, users and projects
-* new custom field format "text" (displayed as a textarea field)
-* project & administration drop down menus in navigation bar for quicker access
-* text formatting is preserved for long text fields (issues, projects and news descriptions)
-* urls and emails are turned into clickable links in long text fields
-* "due date" field added on issues
-* tracker selection filter added on change log
-* Localization plugin replaced with GLoc 1.1.0 (iconv required)
-* error messages internationalization
-* german translation added (thanks to Karim Trott)
-* data locking for issues to prevent update conflicts (using ActiveRecord builtin optimistic locking)
-* new filter in issues list: "Fixed version"
-* active filters are displayed with colored background on issues list
-* custom configuration is now defined in config/config_custom.rb
-* user object no more stored in session (only user_id)
-* news summary field is no longer required
-* tables and forms redesign
-* Fixed: boolean custom field not working
-* Fixed: error messages for custom fields are not displayed
-* Fixed: invalid custom fields should have a red border
-* Fixed: custom fields values are not validated on issue update
-* Fixed: unable to choose an empty value for 'List' custom fields
-* Fixed: no issue categories sorting
-* Fixed: incorrect versions sorting
-
-
-== 2006-07-12 - v0.2.2
-
-* Fixed: bug in "issues list"
-
-
-== 2006-07-09 - v0.2.1
-
-* new databases supported: Oracle, PostgreSQL, SQL Server
-* projects/subprojects hierarchy (1 level of subprojects only)
-* environment information display in admin/info
-* more filter options in issues list (rev6)
-* default language based on browser settings (Accept-Language HTTP header)
-* issues list exportable to CSV (rev6)
-* simple_format and auto_link on long text fields
-* more data validations
-* Fixed: error when all mail notifications are unchecked in admin/mail_options
-* Fixed: all project news are displayed on project summary
-* Fixed: Can't change user password in users/edit
-* Fixed: Error on tables creation with PostgreSQL (rev5)
-* Fixed: SQL error in "issue reports" view with PostgreSQL (rev5)
-
-
-== 2006-06-25 - v0.1.0
-
-* multiple users/multiple projects
-* role based access control
-* issue tracking system
-* fully customizable workflow
-* documents/files repository
-* email notifications on issue creation and update
-* multilanguage support (except for error messages):english, french, spanish
-* online manual in french (unfinished)
diff --git a/trustie2/doc/COPYING b/trustie2/doc/COPYING
deleted file mode 100644
index f21827bc1..000000000
--- a/trustie2/doc/COPYING
+++ /dev/null
@@ -1,339 +0,0 @@
- 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 title 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.
-
-
- Copyright (C)
-
- 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.
-
- , 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.
diff --git a/trustie2/doc/INSTALL b/trustie2/doc/INSTALL
deleted file mode 100644
index 7ea5f7d0d..000000000
--- a/trustie2/doc/INSTALL
+++ /dev/null
@@ -1,106 +0,0 @@
-== Redmine installation
-
-Redmine - project management software
-Copyright (C) 2006-2013 Jean-Philippe Lang
-http://www.redmine.org/
-
-
-== Requirements
-
-* Ruby 1.8.7, 1.9.2, 1.9.3 or 2.0.0
-* RubyGems
-* Bundler >= 1.0.21
-
-* A database:
- * MySQL (tested with MySQL 5.1)
- * PostgreSQL (tested with PostgreSQL 9.1)
- * SQLite3 (tested with SQLite 3.7)
- * SQLServer (tested with SQLServer 2012)
-
-Optional:
-* SCM binaries (e.g. svn, git...), for repository browsing (must be available in PATH)
-* ImageMagick (to enable Gantt export to png images)
-
-== Installation
-
-1. Uncompress the program archive
-
-2. Create an empty utf8 encoded database: "redmine" for example
-
-3. Configure the database parameters in config/database.yml
- for the "production" environment (default database is MySQL and ruby1.9)
-
- If you're running Redmine with MySQL and ruby1.8, replace the adapter name
- with `mysql`
-
-4. Install the required gems by running:
- bundle install --without development test
-
- If ImageMagick is not installed on your system, you should skip the installation
- of the rmagick gem using:
- bundle install --without development test rmagick
-
- Only the gems that are needed by the adapters you've specified in your database
- configuration file are actually installed (eg. if your config/database.yml
- uses the 'mysql2' adapter, then only the mysql2 gem will be installed). Don't
- forget to re-run `bundle install` when you change config/database.yml for using
- other database adapters.
-
- If you need to load some gems that are not required by Redmine core (eg. fcgi),
- you can create a file named Gemfile.local at the root of your redmine directory.
- It will be loaded automatically when running `bundle install`.
-
-5. Generate a session store secret
-
- Redmine stores session data in cookies by default, which requires
- a secret to be generated. Under the application main directory run:
- rake generate_secret_token
-
-6. Create the database structure
-
- Under the application main directory run:
- rake db:migrate RAILS_ENV="production"
-
- It will create all the tables and an administrator account.
-
-7. Setting up permissions (Windows users have to skip this section)
-
- The user who runs Redmine must have write permission on the following
- subdirectories: files, log, tmp & public/plugin_assets.
-
- Assuming you run Redmine with a user named "redmine":
- sudo chown -R redmine:redmine files log tmp public/plugin_assets
- sudo chmod -R 755 files log tmp public/plugin_assets
-
-8. Test the installation by running the WEBrick web server
-
- Under the main application directory run:
- ruby script/rails server -e production
-
- Once WEBrick has started, point your browser to http://localhost:3000/
- You should now see the application welcome page.
-
-9. Use the default administrator account to log in:
- login: admin
- password: admin
-
- Go to "Administration" to load the default configuration data (roles,
- trackers, statuses, workflow) and to adjust the application settings
-
-== SMTP server Configuration
-
-Copy config/configuration.yml.example to config/configuration.yml and
-edit this file to adjust your SMTP settings.
-Do not forget to restart the application after any change to this file.
-
-Please do not enter your SMTP settings in environment.rb.
-
-== References
-
-* http://www.redmine.org/wiki/redmine/RedmineInstall
-* http://www.redmine.org/wiki/redmine/EmailConfiguration
-* http://www.redmine.org/wiki/redmine/RedmineSettings
-* http://www.redmine.org/wiki/redmine/RedmineRepositories
-* http://www.redmine.org/wiki/redmine/RedmineReceivingEmails
-* http://www.redmine.org/wiki/redmine/RedmineReminderEmails
-* http://www.redmine.org/wiki/redmine/RedmineLDAP
diff --git a/trustie2/doc/README_FOR_APP b/trustie2/doc/README_FOR_APP
deleted file mode 100644
index 8bf877515..000000000
--- a/trustie2/doc/README_FOR_APP
+++ /dev/null
@@ -1,28 +0,0 @@
-= Redmine
-
-Redmine is a flexible project management web application written using Ruby on Rails framework.
-
-More details can be found at http://www.redmine.org
-
-= License
-
-Copyright (C) 2006-2013 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.
-
-Icons credits:
-
-* Mark James (Silk Icons) licensed under a Creative Commons Attribution 2.5 License.
-* Yusuke Kamiyamane (Fugue Icons) licensed under a Creative Commons Attribution 3.0 License.
diff --git a/trustie2/doc/RUNNING_TESTS b/trustie2/doc/RUNNING_TESTS
deleted file mode 100644
index b6a53542f..000000000
--- a/trustie2/doc/RUNNING_TESTS
+++ /dev/null
@@ -1,69 +0,0 @@
-Installing gems for testing
-===========================
-
-Remove your .bundle/config if you've already installed Redmine without
-the test dependencies. Then, run `bundle install`.
-
-Running Tests
-=============
-
-Run `rake --tasks test` to see available tests.
-Run `rake test` to run the entire test suite (except the tests for the
-Apache perl module Redmine.pm and Capybara tests, see below).
-
-You can run `ruby test/unit/issue_test.rb` for running a single test case.
-
-Before running tests, you need to configure both development
-and test databases.
-
-Creating test repositories
-==========================
-
-Redmine supports a wide array of different version control systems.
-To test the support, a test repository needs to be created for each of those.
-
-Run `rake --tasks test:scm:setup` for a list of available test-repositories or
-run `rake test:scm:setup:all` to set up all of them. The repositories are
-unpacked into {redmine_root}/tmp/test.
-
-If the test repositories are not present, the tests that need them will be
-skipped.
-
-Creating a test ldap database
-=============================
-
-Redmine supports using LDAP for user authentications. To test LDAP
-with Redmine, load the LDAP export from test/fixtures/ldap/test-ldap.ldif
-into a testing LDAP server. Make sure that the LDAP server can be accessed
-at 127.0.0.1 on port 389.
-
-Setting up the test LDAP server is beyond the scope of this documentation.
-The OpenLDAP project provides a simple LDAP implementation that should work
-good as a test server.
-
-If the LDAP is not available, the tests that need it will be skipped.
-
-Running Redmine.pm tests
-========================
-
-(work in progress)
-
-Running the tests for the Redmine.pm perl module needs a bit more setup.
-You need an Apache server with mod_perl, mod_dav_svn and Redmine.pm configured.
-See: http://www.redmine.org/projects/redmine/wiki/Repositories_access_control_with_apache_mod_dav_svn_and_mod_perl
-
-You need an empty repository accessible at http://127.0.0.1/svn/ecookbook
-Then, you can run the tests with:
-`ruby test\extra\redmine_pm\repository_subversion_test.rb`
-
-If you svn server is not running on localhost, you can use the REDMINE_TEST_DAV_SERVER
-environment variable to specify another host.
-
-Running Capybara tests
-======================
-
-You need to have PhantomJS WebDriver listening on port 4444:
-`phantomjs --webdriver 4444`
-
-Capybara tests can be run with:
-`rake test:ui`
diff --git a/trustie2/doc/UPGRADING b/trustie2/doc/UPGRADING
deleted file mode 100644
index 2afef483c..000000000
--- a/trustie2/doc/UPGRADING
+++ /dev/null
@@ -1,79 +0,0 @@
-== Redmine upgrade
-
-Redmine - project management software
-Copyright (C) 2006-2013 Jean-Philippe Lang
-http://www.redmine.org/
-
-
-== Upgrading
-
-1. Uncompress the program archive in a new directory
-
-2. Copy your database settings (RAILS_ROOT/config/database.yml)
- and your configuration file (RAILS_ROOT/config/configuration.yml)
- into the new config directory
- Note: before Redmine 1.2, SMTP configuration was stored in
- config/email.yml. It should now be stored in config/configuration.yml.
-
-3. Copy the RAILS_ROOT/files directory content into your new installation
- This directory contains all the attached files.
-
-4. Copy the folders of the installed plugins and themes into new installation
- Plugins must be stored in the [redmine_root]/plugins directory
- Themes must be stored in the [redmine_root]/public/themes directory
-
- WARNING: plugins from your previous Redmine version may not be compatible
- with the Redmine version you're upgrading to.
-
-5. Install the required gems by running:
- bundle install --without development test
-
- If ImageMagick is not installed on your system, you should skip the installation
- of the rmagick gem using:
- bundle install --without development test rmagick
-
- Only the gems that are needed by the adapters you've specified in your database
- configuration file are actually installed (eg. if your config/database.yml
- uses the 'mysql2' adapter, then only the mysql2 gem will be installed). Don't
- forget to re-run `bundle install` when you change config/database.yml for using
- other database adapters.
-
- If you need to load some gems that are not required by Redmine core (eg. fcgi),
- you can create a file named Gemfile.local at the root of your redmine directory.
- It will be loaded automatically when running `bundle install`.
-
-6. Generate a session store secret
-
- Redmine stores session data in cookies by default, which requires
- a secret to be generated. Under the new application directory run:
- rake generate_secret_token
-
- DO NOT REPLACE OR EDIT ANY OTHER FILES.
-
-7. Migrate your database
-
- If you are upgrading to Rails 2.3.14 as part of this migration, you
- need to upgrade the plugin migrations before running the plugin migrations
- using:
- rake db:migrate:upgrade_plugin_migrations RAILS_ENV="production"
-
- Please make a backup before doing this! Under the new application
- directory run:
- rake db:migrate RAILS_ENV="production"
-
- If you have installed any plugins, you should also run their database
- migrations using:
- rake db:migrate_plugins RAILS_ENV="production"
-
-8. Clear the cache and the existing sessions by running:
- rake tmp:cache:clear
- rake tmp:sessions:clear
-
-9. Restart the application server (e.g. mongrel, thin, passenger)
-
-10. Finally go to "Administration -> Roles & permissions" to check/set permissions
- for new features, if any
-
-== References
-
-* http://www.redmine.org/wiki/redmine/RedmineUpgrade
diff --git a/trustie2/extra/mail_handler/rdm-mailhandler.rb b/trustie2/extra/mail_handler/rdm-mailhandler.rb
deleted file mode 100644
index f46c882b1..000000000
--- a/trustie2/extra/mail_handler/rdm-mailhandler.rb
+++ /dev/null
@@ -1,162 +0,0 @@
-#!/usr/bin/env ruby
-
-require 'net/http'
-require 'net/https'
-require 'uri'
-require 'optparse'
-
-module Net
- class HTTPS < HTTP
- def self.post_form(url, params, headers, options={})
- request = Post.new(url.path)
- request.form_data = params
- request.initialize_http_header(headers)
- request.basic_auth url.user, url.password if url.user
- http = new(url.host, url.port)
- http.use_ssl = (url.scheme == 'https')
- if options[:no_check_certificate]
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
- end
- http.start {|h| h.request(request) }
- end
- end
-end
-
-class RedmineMailHandler
- VERSION = '0.2.3'
-
- attr_accessor :verbose, :issue_attributes, :allow_override, :unknown_user, :default_group, :no_permission_check,
- :url, :key, :no_check_certificate, :no_account_notice, :no_notification
-
- def initialize
- self.issue_attributes = {}
-
- optparse = OptionParser.new do |opts|
- opts.banner = "Usage: rdm-mailhandler.rb [options] --url= --key="
- opts.separator("")
- opts.separator("Reads an email from standard input and forward it to a Redmine server through a HTTP request.")
- opts.separator("")
- opts.separator("Required arguments:")
- opts.on("-u", "--url URL", "URL of the Redmine server") {|v| self.url = v}
- opts.on("-k", "--key KEY", "Redmine API key") {|v| self.key = v}
- opts.separator("")
- opts.separator("General options:")
- opts.on("--no-permission-check", "disable permission checking when receiving",
- "the email") {self.no_permission_check = '1'}
- opts.on("--key-file FILE", "path to a file that contains the Redmine",
- "API key (use this option instead of --key",
- "if you don't the key to appear in the",
- "command line)") {|v| read_key_from_file(v)}
- opts.on("--no-check-certificate", "do not check server certificate") {self.no_check_certificate = true}
- opts.on("-h", "--help", "show this help") {puts opts; exit 1}
- opts.on("-v", "--verbose", "show extra information") {self.verbose = true}
- opts.on("-V", "--version", "show version information and exit") {puts VERSION; exit}
- opts.separator("")
- opts.separator("User creation options:")
- opts.on("--unknown-user ACTION", "how to handle emails from an unknown user",
- "ACTION can be one of the following values:",
- "* ignore: email is ignored (default)",
- "* accept: accept as anonymous user",
- "* create: create a user account") {|v| self.unknown_user = v}
- opts.on("--default-group GROUP", "add created user to GROUP (none by default)",
- "GROUP can be a comma separated list of groups") { |v| self.default_group = v}
- opts.on("--no-account-notice", "don't send account information to the newly",
- "created user") { |v| self.no_account_notice = '1'}
- opts.on("--no-notification", "disable email notifications for the created",
- "user") { |v| self.no_notification = '1'}
- opts.separator("")
- opts.separator("Issue attributes control options:")
- opts.on("-p", "--project PROJECT", "identifier of the target project") {|v| self.issue_attributes['project'] = v}
- opts.on("-s", "--status STATUS", "name of the target status") {|v| self.issue_attributes['status'] = v}
- opts.on("-t", "--tracker TRACKER", "name of the target tracker") {|v| self.issue_attributes['tracker'] = v}
- opts.on( "--category CATEGORY", "name of the target category") {|v| self.issue_attributes['category'] = v}
- opts.on( "--priority PRIORITY", "name of the target priority") {|v| self.issue_attributes['priority'] = v}
- opts.on("-o", "--allow-override ATTRS", "allow email content to override attributes",
- "specified by previous options",
- "ATTRS is a comma separated list of attributes") {|v| self.allow_override = v}
- opts.separator("")
- opts.separator("Examples:")
- opts.separator("No project specified. Emails MUST contain the 'Project' keyword:")
- opts.separator(" rdm-mailhandler.rb --url http://redmine.domain.foo --key secret")
- opts.separator("")
- opts.separator("Fixed project and default tracker specified, but emails can override")
- opts.separator("both tracker and priority attributes using keywords:")
- opts.separator(" rdm-mailhandler.rb --url https://domain.foo/redmine --key secret \\")
- opts.separator(" --project foo \\")
- opts.separator(" --tracker bug \\")
- opts.separator(" --allow-override tracker,priority")
-
- opts.summary_width = 27
- end
- optparse.parse!
-
- unless url && key
- puts "Some arguments are missing. Use `rdm-mailhandler.rb --help` for getting help."
- exit 1
- end
- end
-
- def submit(email)
- uri = url.gsub(%r{/*$}, '') + '/mail_handler'
-
- headers = { 'User-Agent' => "Redmine mail handler/#{VERSION}" }
-
- data = { 'key' => key, 'email' => email,
- 'allow_override' => allow_override,
- 'unknown_user' => unknown_user,
- 'default_group' => default_group,
- 'no_account_notice' => no_account_notice,
- 'no_notification' => no_notification,
- 'no_permission_check' => no_permission_check}
- issue_attributes.each { |attr, value| data["issue[#{attr}]"] = value }
-
- debug "Posting to #{uri}..."
- begin
- response = Net::HTTPS.post_form(URI.parse(uri), data, headers, :no_check_certificate => no_check_certificate)
- rescue SystemCallError => e # connection refused, etc.
- warn "An error occured while contacting your Redmine server: #{e.message}"
- return 75 # temporary failure
- end
- debug "Response received: #{response.code}"
-
- case response.code.to_i
- when 403
- warn "Request was denied by your Redmine server. " +
- "Make sure that 'WS for incoming emails' is enabled in application settings and that you provided the correct API key."
- return 77
- when 422
- warn "Request was denied by your Redmine server. " +
- "Possible reasons: email is sent from an invalid email address or is missing some information."
- return 77
- when 400..499
- warn "Request was denied by your Redmine server (#{response.code})."
- return 77
- when 500..599
- warn "Failed to contact your Redmine server (#{response.code})."
- return 75
- when 201
- debug "Proccessed successfully"
- return 0
- else
- return 1
- end
- end
-
- private
-
- def debug(msg)
- puts msg if verbose
- end
-
- def read_key_from_file(filename)
- begin
- self.key = File.read(filename).strip
- rescue Exception => e
- $stderr.puts "Unable to read the key from #{filename}:\n#{e.message}"
- exit 1
- end
- end
-end
-
-handler = RedmineMailHandler.new
-exit(handler.submit(STDIN.read))
diff --git a/trustie2/extra/sample_plugin/README b/trustie2/extra/sample_plugin/README
deleted file mode 100644
index 5fe8a2a31..000000000
--- a/trustie2/extra/sample_plugin/README
+++ /dev/null
@@ -1,15 +0,0 @@
-== Sample plugin
-
-This is a sample plugin for Redmine
-
-== Installation
-
-1. Copy the plugin directory into the "plugins" directory at the root
- of your Redmine directory
-
-2. Migrate and copy plugin assets:
- rake redmine:plugins
-
-3. Start Redmine
-
-Installed plugins are listed and can be configured from 'Admin -> Plugins' screen.
diff --git a/trustie2/extra/sample_plugin/app/controllers/example_controller.rb b/trustie2/extra/sample_plugin/app/controllers/example_controller.rb
deleted file mode 100644
index dbc271a1b..000000000
--- a/trustie2/extra/sample_plugin/app/controllers/example_controller.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# Sample plugin controller
-class ExampleController < ApplicationController
- unloadable
-
- layout 'base'
- before_filter :find_project, :authorize
- menu_item :sample_plugin
-
- def say_hello
- @value = Setting.plugin_sample_plugin['sample_setting']
- end
-
- def say_goodbye
- end
-
-private
- def find_project
- @project=Project.find(params[:id])
- end
-end
diff --git a/trustie2/extra/sample_plugin/app/models/meeting.rb b/trustie2/extra/sample_plugin/app/models/meeting.rb
deleted file mode 100644
index c424bdec4..000000000
--- a/trustie2/extra/sample_plugin/app/models/meeting.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class Meeting < ActiveRecord::Base
- belongs_to :project
-
- acts_as_event :title => Proc.new {|o| "#{o.scheduled_on} Meeting"},
- :datetime => :scheduled_on,
- :author => nil,
- :url => Proc.new {|o| {:controller => 'meetings', :action => 'show', :id => o.id}}
-
- acts_as_activity_provider :timestamp => 'scheduled_on',
- :find_options => { :include => :project }
-end
diff --git a/trustie2/extra/sample_plugin/app/views/example/say_goodbye.html.erb b/trustie2/extra/sample_plugin/app/views/example/say_goodbye.html.erb
deleted file mode 100644
index 2e3026a2a..000000000
--- a/trustie2/extra/sample_plugin/app/views/example/say_goodbye.html.erb
+++ /dev/null
@@ -1,7 +0,0 @@
-Good Bye
-
-<%= l(:text_say_goodbye) %>
-
-<% content_for :header_tags do %>
- <%= stylesheet_link_tag 'example', :plugin => 'sample_plugin', :media => "screen" %>
-<% end %>
diff --git a/trustie2/extra/sample_plugin/app/views/example/say_hello.html.erb b/trustie2/extra/sample_plugin/app/views/example/say_hello.html.erb
deleted file mode 100644
index ba3d8bd8e..000000000
--- a/trustie2/extra/sample_plugin/app/views/example/say_hello.html.erb
+++ /dev/null
@@ -1,15 +0,0 @@
-Hello
-
-<%= l(:text_say_hello) %>
-
-: <%= @value %>
-
-<%= link_to('Good bye', :action => 'say_goodbye', :id => @project) if User.current.allowed_to?(:example_say_goodbye, @project) %>
-
-<% content_for :sidebar do %>
- Adding content to the sidebar...
-<% end %>
-
-<% content_for :header_tags do %>
- <%= stylesheet_link_tag 'example', :plugin => 'sample_plugin', :media => "screen" %>
-<% end %>
diff --git a/trustie2/extra/sample_plugin/app/views/my/blocks/_sample_block.html.erb b/trustie2/extra/sample_plugin/app/views/my/blocks/_sample_block.html.erb
deleted file mode 100644
index c19e49739..000000000
--- a/trustie2/extra/sample_plugin/app/views/my/blocks/_sample_block.html.erb
+++ /dev/null
@@ -1,3 +0,0 @@
-Sample block
-
-You are <%= h(User.current) %> and this is a sample block for My Page added from a plugin.
diff --git a/trustie2/extra/sample_plugin/app/views/settings/_sample_plugin_settings.html.erb b/trustie2/extra/sample_plugin/app/views/settings/_sample_plugin_settings.html.erb
deleted file mode 100644
index bf06e2666..000000000
--- a/trustie2/extra/sample_plugin/app/views/settings/_sample_plugin_settings.html.erb
+++ /dev/null
@@ -1,3 +0,0 @@
-<%= text_field_tag 'settings[sample_setting]', @settings['sample_setting'] %>
-
-<%= text_field_tag 'settings[foo]', @settings['foo'] %>
diff --git a/trustie2/extra/sample_plugin/assets/images/it_works.png b/trustie2/extra/sample_plugin/assets/images/it_works.png
deleted file mode 100644
index 441f368d2..000000000
Binary files a/trustie2/extra/sample_plugin/assets/images/it_works.png and /dev/null differ
diff --git a/trustie2/extra/sample_plugin/assets/stylesheets/example.css b/trustie2/extra/sample_plugin/assets/stylesheets/example.css
deleted file mode 100644
index 8038567a4..000000000
--- a/trustie2/extra/sample_plugin/assets/stylesheets/example.css
+++ /dev/null
@@ -1 +0,0 @@
-.icon-example-works { background-image: url(../images/it_works.png); }
diff --git a/trustie2/extra/sample_plugin/config/locales/en.yml b/trustie2/extra/sample_plugin/config/locales/en.yml
deleted file mode 100644
index 5a010003b..000000000
--- a/trustie2/extra/sample_plugin/config/locales/en.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# Sample plugin
-en:
- label_plugin_example: Sample Plugin
- label_meeting_plural: Meetings
- text_say_hello: Plugin say 'Hello'
- text_say_goodbye: Plugin say 'Good bye'
diff --git a/trustie2/extra/sample_plugin/config/locales/fr.yml b/trustie2/extra/sample_plugin/config/locales/fr.yml
deleted file mode 100644
index 1fae8e4e0..000000000
--- a/trustie2/extra/sample_plugin/config/locales/fr.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-# Sample plugin
-fr:
- label_plugin_example: Plugin exemple
- label_meeting_plural: Meetings
- text_say_hello: Plugin dit 'Bonjour'
- text_say_goodbye: Plugin dit 'Au revoir'
diff --git a/trustie2/extra/sample_plugin/config/routes.rb b/trustie2/extra/sample_plugin/config/routes.rb
deleted file mode 100644
index 53428a7c5..000000000
--- a/trustie2/extra/sample_plugin/config/routes.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# Plugin's routes
-# See: http://guides.rubyonrails.org/routing.html
-
-match 'projects/:id/hello', :to => 'example#say_hello', :via => 'get'
-match 'projects/:id/bye', :to => 'example#say_goodbye', :via => 'get'
-
-resources 'meetings'
diff --git a/trustie2/extra/sample_plugin/db/migrate/001_create_meetings.rb b/trustie2/extra/sample_plugin/db/migrate/001_create_meetings.rb
deleted file mode 100644
index fec9c8bd1..000000000
--- a/trustie2/extra/sample_plugin/db/migrate/001_create_meetings.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# Sample plugin migration
-# Use rake db:migrate_plugins to migrate installed plugins
-class CreateMeetings < ActiveRecord::Migration
- def self.up
- create_table :meetings do |t|
- t.column :project_id, :integer, :null => false
- t.column :description, :string
- t.column :scheduled_on, :datetime
- end
- end
-
- def self.down
- drop_table :meetings
- end
-end
diff --git a/trustie2/extra/sample_plugin/init.rb b/trustie2/extra/sample_plugin/init.rb
deleted file mode 100644
index be7eeceb6..000000000
--- a/trustie2/extra/sample_plugin/init.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-Rails.logger.info 'Starting Example plugin for RedMine'
-
-Redmine::Plugin.register :sample_plugin do
- name 'Example plugin'
- author 'Author name'
- description 'This is a sample plugin for Redmine'
- version '0.0.1'
- settings :default => {'sample_setting' => 'value', 'foo'=>'bar'}, :partial => 'settings/sample_plugin_settings'
-
- # This plugin adds a project module
- # It can be enabled/disabled at project level (Project settings -> Modules)
- project_module :example_module do
- # A public action
- permission :example_say_hello, {:example => [:say_hello]}, :public => true
- # This permission has to be explicitly given
- # It will be listed on the permissions screen
- permission :example_say_goodbye, {:example => [:say_goodbye]}
- # This permission can be given to project members only
- permission :view_meetings, {:meetings => [:index, :show]}, :require => :member
- end
-
- # A new item is added to the project menu
- menu :project_menu, :sample_plugin, { :controller => 'example', :action => 'say_hello' }, :caption => 'Sample'
-
- # Meetings are added to the activity view
- activity_provider :meetings
-end
diff --git a/trustie2/extra/sample_plugin/test/integration/routing_test.rb b/trustie2/extra/sample_plugin/test/integration/routing_test.rb
deleted file mode 100644
index bfc2f2b78..000000000
--- a/trustie2/extra/sample_plugin/test/integration/routing_test.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-
-require File.expand_path(File.dirname(__FILE__) + '../../../../../test/test_helper')
-
-class SamplePluginRoutingTest < ActionDispatch::IntegrationTest
- def test_example
- assert_routing(
- { :method => 'get', :path => "/projects/1234/hello" },
- { :controller => 'example', :action => 'say_hello',
- :id => '1234' }
- )
- end
-end
diff --git a/trustie2/extra/svn/Redmine.pm b/trustie2/extra/svn/Redmine.pm
deleted file mode 100644
index ac7387122..000000000
--- a/trustie2/extra/svn/Redmine.pm
+++ /dev/null
@@ -1,544 +0,0 @@
-package Apache::Authn::Redmine;
-
-=head1 Apache::Authn::Redmine
-
-Redmine - a mod_perl module to authenticate webdav subversion users
-against redmine database
-
-=head1 SYNOPSIS
-
-This module allow anonymous users to browse public project and
-registred users to browse and commit their project. Authentication is
-done against the redmine database or the LDAP configured in redmine.
-
-This method is far simpler than the one with pam_* and works with all
-database without an hassle but you need to have apache/mod_perl on the
-svn server.
-
-=head1 INSTALLATION
-
-For this to automagically work, you need to have a recent reposman.rb
-(after r860) and if you already use reposman, read the last section to
-migrate.
-
-Sorry ruby users but you need some perl modules, at least mod_perl2,
-DBI and DBD::mysql (or the DBD driver for you database as it should
-work on allmost all databases).
-
-On debian/ubuntu you must do :
-
- aptitude install libapache-dbi-perl libapache2-mod-perl2 libdbd-mysql-perl
-
-If your Redmine users use LDAP authentication, you will also need
-Authen::Simple::LDAP (and IO::Socket::SSL if LDAPS is used):
-
- aptitude install libauthen-simple-ldap-perl libio-socket-ssl-perl
-
-=head1 CONFIGURATION
-
- ## This module has to be in your perl path
- ## eg: /usr/lib/perl5/Apache/Authn/Redmine.pm
- PerlLoadModule Apache::Authn::Redmine
-
- DAV svn
- SVNParentPath "/var/svn"
-
- AuthType Basic
- AuthName redmine
- Require valid-user
-
- PerlAccessHandler Apache::Authn::Redmine::access_handler
- PerlAuthenHandler Apache::Authn::Redmine::authen_handler
-
- ## for mysql
- RedmineDSN "DBI:mysql:database=databasename;host=my.db.server"
- ## for postgres
- # RedmineDSN "DBI:Pg:dbname=databasename;host=my.db.server"
-
- RedmineDbUser "redmine"
- RedmineDbPass "password"
- ## Optional where clause (fulltext search would be slow and
- ## database dependant).
- # RedmineDbWhereClause "and members.role_id IN (1,2)"
- ## Optional credentials cache size
- # RedmineCacheCredsMax 50
-
-
-To be able to browse repository inside redmine, you must add something
-like that :
-
-
- DAV svn
- SVNParentPath "/var/svn"
- Order deny,allow
- Deny from all
- # only allow reading orders
-
- Allow from redmine.server.ip
-
-
-
-and you will have to use this reposman.rb command line to create repository :
-
- reposman.rb --redmine my.redmine.server --svn-dir /var/svn --owner www-data -u http://svn.server/svn-private/
-
-=head1 REPOSITORIES NAMING
-
-A projet repository must be named with the projet identifier. In case
-of multiple repositories for the same project, use the project identifier
-and the repository identifier separated with a dot:
-
- /var/svn/foo
- /var/svn/foo.otherrepo
-
-=head1 MIGRATION FROM OLDER RELEASES
-
-If you use an older reposman.rb (r860 or before), you need to change
-rights on repositories to allow the apache user to read and write
-S
-
- sudo chown -R www-data /var/svn/*
- sudo chmod -R u+w /var/svn/*
-
-And you need to upgrade at least reposman.rb (after r860).
-
-=head1 GIT SMART HTTP SUPPORT
-
-Git's smart HTTP protocol (available since Git 1.7.0) will not work with the
-above settings. Redmine.pm normally does access control depending on the HTTP
-method used: read-only methods are OK for everyone in public projects and
-members with read rights in private projects. The rest require membership with
-commit rights in the project.
-
-However, this scheme doesn't work for Git's smart HTTP protocol, as it will use
-POST even for a simple clone. Instead, read-only requests must be detected using
-the full URL (including the query string): anything that doesn't belong to the
-git-receive-pack service is read-only.
-
-To activate this mode of operation, add this line inside your
-block:
-
- RedmineGitSmartHttp yes
-
-Here's a sample Apache configuration which integrates git-http-backend with
-a MySQL database and this new option:
-
- SetEnv GIT_PROJECT_ROOT /var/www/git/
- SetEnv GIT_HTTP_EXPORT_ALL
- ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
-
- Order allow,deny
- Allow from all
-
- AuthType Basic
- AuthName Git
- Require valid-user
-
- PerlAccessHandler Apache::Authn::Redmine::access_handler
- PerlAuthenHandler Apache::Authn::Redmine::authen_handler
- # for mysql
- RedmineDSN "DBI:mysql:database=redmine;host=127.0.0.1"
- RedmineDbUser "redmine"
- RedmineDbPass "xxx"
- RedmineGitSmartHttp yes
-
-
-Make sure that all the names of the repositories under /var/www/git/ have a
-matching identifier for some project: /var/www/git/myproject and
-/var/www/git/myproject.git will work. You can put both bare and non-bare
-repositories in /var/www/git, though bare repositories are strongly
-recommended. You should create them with the rights of the user running Redmine,
-like this:
-
- cd /var/www/git
- sudo -u user-running-redmine mkdir myproject
- cd myproject
- sudo -u user-running-redmine git init --bare
-
-Once you have activated this option, you have three options when cloning a
-repository:
-
-- Cloning using "http://user@host/git/repo(.git)" works, but will ask for the password
- all the time.
-
-- Cloning with "http://user:pass@host/git/repo(.git)" does not have this problem, but
- this could reveal accidentally your password to the console in some versions
- of Git, and you would have to ensure that .git/config is not readable except
- by the owner for each of your projects.
-
-- Use "http://host/git/repo(.git)", and store your credentials in the ~/.netrc
- file. This is the recommended solution, as you only have one file to protect
- and passwords will not be leaked accidentally to the console.
-
- IMPORTANT NOTE: It is *very important* that the file cannot be read by other
- users, as it will contain your password in cleartext. To create the file, you
- can use the following commands, replacing yourhost, youruser and yourpassword
- with the right values:
-
- touch ~/.netrc
- chmod 600 ~/.netrc
- echo -e "machine yourhost\nlogin youruser\npassword yourpassword" > ~/.netrc
-
-=cut
-
-use strict;
-use warnings FATAL => 'all', NONFATAL => 'redefine';
-
-use DBI;
-use Digest::SHA;
-# optional module for LDAP authentication
-my $CanUseLDAPAuth = eval("use Authen::Simple::LDAP; 1");
-
-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 ();
-
-# use Apache2::Directive qw();
-
-my @directives = (
- {
- name => 'RedmineDSN',
- 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 => 'RedmineDbUser',
- req_override => OR_AUTHCFG,
- args_how => TAKE1,
- },
- {
- name => 'RedmineDbPass',
- req_override => OR_AUTHCFG,
- args_how => TAKE1,
- },
- {
- name => 'RedmineDbWhereClause',
- req_override => OR_AUTHCFG,
- args_how => TAKE1,
- },
- {
- name => 'RedmineCacheCredsMax',
- req_override => OR_AUTHCFG,
- args_how => TAKE1,
- errmsg => 'RedmineCacheCredsMax must be decimal number',
- },
- {
- name => 'RedmineGitSmartHttp',
- req_override => OR_AUTHCFG,
- args_how => TAKE1,
- },
-);
-
-sub RedmineDSN {
- my ($self, $parms, $arg) = @_;
- $self->{RedmineDSN} = $arg;
- my $query = "SELECT
- users.hashed_password, users.salt, users.auth_source_id, roles.permissions, projects.status
- FROM projects, users, roles
- WHERE
- users.login=?
- AND projects.identifier=?
- AND users.status=1
- AND (
- roles.id IN (SELECT member_roles.role_id FROM members, member_roles WHERE members.user_id = users.id AND members.project_id = projects.id AND members.id = member_roles.member_id)
- OR
- (roles.builtin=1 AND cast(projects.is_public as CHAR) IN ('t', '1'))
- )
- AND roles.permissions IS NOT NULL";
- $self->{RedmineQuery} = trim($query);
-}
-
-sub RedmineDbUser { set_val('RedmineDbUser', @_); }
-sub RedmineDbPass { set_val('RedmineDbPass', @_); }
-sub RedmineDbWhereClause {
- my ($self, $parms, $arg) = @_;
- $self->{RedmineQuery} = trim($self->{RedmineQuery}.($arg ? $arg : "")." ");
-}
-
-sub RedmineCacheCredsMax {
- my ($self, $parms, $arg) = @_;
- if ($arg) {
- $self->{RedmineCachePool} = APR::Pool->new;
- $self->{RedmineCacheCreds} = APR::Table::make($self->{RedmineCachePool}, $arg);
- $self->{RedmineCacheCredsCount} = 0;
- $self->{RedmineCacheCredsMax} = $arg;
- }
-}
-
-sub RedmineGitSmartHttp {
- my ($self, $parms, $arg) = @_;
- $arg = lc $arg;
-
- if ($arg eq "yes" || $arg eq "true") {
- $self->{RedmineGitSmartHttp} = 1;
- } else {
- $self->{RedmineGitSmartHttp} = 0;
- }
-}
-
-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 HEAD PROPFIND REPORT OPTIONS/;
-
-sub request_is_read_only {
- my ($r) = @_;
- my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
-
- # Do we use Git's smart HTTP protocol, or not?
- if (defined $cfg->{RedmineGitSmartHttp} and $cfg->{RedmineGitSmartHttp}) {
- my $uri = $r->unparsed_uri;
- my $location = $r->location;
- my $is_read_only = $uri !~ m{^$location/*[^/]+/+(info/refs\?service=)?git\-receive\-pack$}o;
- return $is_read_only;
- } else {
- # Standard behaviour: check the HTTP method
- my $method = $r->method;
- return defined $read_only_methods{$method};
- }
-}
-
-sub access_handler {
- my $r = shift;
-
- unless ($r->some_auth_required) {
- $r->log_reason("No authentication has been configured");
- return FORBIDDEN;
- }
-
- return OK unless request_is_read_only($r);
-
- my $project_id = get_project_identifier($r);
-
- $r->set_handlers(PerlAuthenHandler => [\&OK])
- if is_public_project($project_id, $r) && anonymous_role_allows_browse_repository($r);
-
- return OK
-}
-
-sub authen_handler {
- my $r = shift;
-
- my ($res, $redmine_pass) = $r->get_basic_auth_pw();
- return $res unless $res == OK;
-
- if (is_member($r->user, $redmine_pass, $r)) {
- return OK;
- } else {
- $r->note_auth_failure();
- return DECLINED;
- }
-}
-
-# check if authentication is forced
-sub is_authentication_forced {
- my $r = shift;
-
- my $dbh = connect_database($r);
- my $sth = $dbh->prepare(
- "SELECT value FROM settings where settings.name = 'login_required';"
- );
-
- $sth->execute();
- my $ret = 0;
- if (my @row = $sth->fetchrow_array) {
- if ($row[0] eq "1" || $row[0] eq "t") {
- $ret = 1;
- }
- }
- $sth->finish();
- undef $sth;
-
- $dbh->disconnect();
- undef $dbh;
-
- $ret;
-}
-
-sub is_public_project {
- my $project_id = shift;
- my $r = shift;
-
- if (is_authentication_forced($r)) {
- return 0;
- }
-
- my $dbh = connect_database($r);
- my $sth = $dbh->prepare(
- "SELECT is_public FROM projects WHERE projects.identifier = ? AND projects.status <> 9;"
- );
-
- $sth->execute($project_id);
- my $ret = 0;
- if (my @row = $sth->fetchrow_array) {
- if ($row[0] eq "1" || $row[0] eq "t") {
- $ret = 1;
- }
- }
- $sth->finish();
- undef $sth;
- $dbh->disconnect();
- undef $dbh;
-
- $ret;
-}
-
-sub anonymous_role_allows_browse_repository {
- my $r = shift;
-
- my $dbh = connect_database($r);
- my $sth = $dbh->prepare(
- "SELECT permissions FROM roles WHERE builtin = 2;"
- );
-
- $sth->execute();
- my $ret = 0;
- if (my @row = $sth->fetchrow_array) {
- if ($row[0] =~ /:browse_repository/) {
- $ret = 1;
- }
- }
- $sth->finish();
- undef $sth;
- $dbh->disconnect();
- undef $dbh;
-
- $ret;
-}
-
-# perhaps we should use repository right (other read right) to check public access.
-# it could be faster BUT it doesn't work for the moment.
-# sub is_public_project_by_file {
-# my $project_id = shift;
-# my $r = shift;
-
-# my $tree = Apache2::Directive::conftree();
-# my $node = $tree->lookup('Location', $r->location);
-# my $hash = $node->as_hash;
-
-# my $svnparentpath = $hash->{SVNParentPath};
-# my $repos_path = $svnparentpath . "/" . $project_id;
-# return 1 if (stat($repos_path))[2] & 00007;
-# }
-
-sub is_member {
- my $redmine_user = shift;
- my $redmine_pass = shift;
- my $r = shift;
-
- my $dbh = connect_database($r);
- my $project_id = get_project_identifier($r);
-
- my $pass_digest = Digest::SHA::sha1_hex($redmine_pass);
-
- my $access_mode = request_is_read_only($r) ? "R" : "W";
-
- my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
- my $usrprojpass;
- if ($cfg->{RedmineCacheCredsMax}) {
- $usrprojpass = $cfg->{RedmineCacheCreds}->get($redmine_user.":".$project_id.":".$access_mode);
- return 1 if (defined $usrprojpass and ($usrprojpass eq $pass_digest));
- }
- my $query = $cfg->{RedmineQuery};
- my $sth = $dbh->prepare($query);
- $sth->execute($redmine_user, $project_id);
-
- my $ret;
- while (my ($hashed_password, $salt, $auth_source_id, $permissions, $project_status) = $sth->fetchrow_array) {
- if ($project_status eq "9" || ($project_status ne "1" && $access_mode eq "W")) {
- last;
- }
-
- unless ($auth_source_id) {
- my $method = $r->method;
- my $salted_password = Digest::SHA::sha1_hex($salt.$pass_digest);
- if ($hashed_password eq $salted_password && (($access_mode eq "R" && $permissions =~ /:browse_repository/) || $permissions =~ /:commit_access/) ) {
- $ret = 1;
- last;
- }
- } elsif ($CanUseLDAPAuth) {
- 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 $bind_as = $rowldap[3] ? $rowldap[3] : "";
- my $bind_pw = $rowldap[4] ? $rowldap[4] : "";
- if ($bind_as =~ m/\$login/) {
- # replace $login with $redmine_user and use $redmine_pass
- $bind_as =~ s/\$login/$redmine_user/g;
- $bind_pw = $redmine_pass
- }
- my $ldap = Authen::Simple::LDAP->new(
- host => ($rowldap[2] eq "1" || $rowldap[2] eq "t") ? "ldaps://$rowldap[0]:$rowldap[1]" : $rowldap[0],
- port => $rowldap[1],
- basedn => $rowldap[5],
- binddn => $bind_as,
- bindpw => $bind_pw,
- filter => "(".$rowldap[6]."=%s)"
- );
- my $method = $r->method;
- $ret = 1 if ($ldap->authenticate($redmine_user, $redmine_pass) && (($access_mode eq "R" && $permissions =~ /:browse_repository/) || $permissions =~ /:commit_access/));
-
- }
- $sthldap->finish();
- undef $sthldap;
- }
- }
- $sth->finish();
- undef $sth;
- $dbh->disconnect();
- undef $dbh;
-
- if ($cfg->{RedmineCacheCredsMax} and $ret) {
- if (defined $usrprojpass) {
- $cfg->{RedmineCacheCreds}->set($redmine_user.":".$project_id.":".$access_mode, $pass_digest);
- } else {
- if ($cfg->{RedmineCacheCredsCount} < $cfg->{RedmineCacheCredsMax}) {
- $cfg->{RedmineCacheCreds}->set($redmine_user.":".$project_id.":".$access_mode, $pass_digest);
- $cfg->{RedmineCacheCredsCount}++;
- } else {
- $cfg->{RedmineCacheCreds}->clear();
- $cfg->{RedmineCacheCredsCount} = 0;
- }
- }
- }
-
- $ret;
-}
-
-sub get_project_identifier {
- my $r = shift;
-
- my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
- my $location = $r->location;
- $location =~ s/\.git$// if (defined $cfg->{RedmineGitSmartHttp} and $cfg->{RedmineGitSmartHttp});
- my ($identifier) = $r->uri =~ m{$location/*([^/.]+)};
- $identifier;
-}
-
-sub connect_database {
- my $r = shift;
-
- my $cfg = Apache2::Module::get_config(__PACKAGE__, $r->server, $r->per_dir_config);
- return DBI->connect($cfg->{RedmineDSN}, $cfg->{RedmineDbUser}, $cfg->{RedmineDbPass});
-}
-
-1;
diff --git a/trustie2/extra/svn/reposman.rb b/trustie2/extra/svn/reposman.rb
deleted file mode 100644
index d79ad2695..000000000
--- a/trustie2/extra/svn/reposman.rb
+++ /dev/null
@@ -1,289 +0,0 @@
-#!/usr/bin/env ruby
-
-require 'optparse'
-require 'find'
-require 'etc'
-require 'rubygems'
-
-Version = "1.4"
-SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
-
-$verbose = 0
-$quiet = false
-$redmine_host = ''
-$repos_base = ''
-$svn_owner = 'root'
-$svn_group = 'root'
-$use_groupid = true
-$svn_url = false
-$test = false
-$force = 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
-
-def read_key_from_file(filename)
- begin
- $api_key = File.read(filename).strip
- rescue Exception => e
- $stderr.puts "Unable to read the key from #{filename}: #{e.message}"
- exit 1
- end
-end
-
-def set_scm(scm)
- $scm = scm.capitalize
- unless SUPPORTED_SCM.include?($scm)
- log("Invalid SCM: #{$scm}\nValid SCM are: #{SUPPORTED_SCM.join(', ')}", :exit => true)
- end
-end
-
-optparse = OptionParser.new do |opts|
- opts.banner = "Usage: reposman.rb [OPTIONS...] -s [DIR] -r [HOST] -k [KEY]"
- opts.separator("")
- opts.separator("Manages your repositories with Redmine.")
- opts.separator("")
- opts.separator("Required arguments:")
- opts.on("-s", "--svn-dir DIR", "use DIR as base directory for svn repositories") {|v| $repos_base = v}
- opts.on("-r", "--redmine-host HOST","assume Redmine is hosted on HOST. Examples:",
- " -r redmine.example.net",
- " -r http://redmine.example.net",
- " -r https://redmine.example.net") {|v| $redmine_host = v}
- opts.on("-k", "--key KEY", "use KEY as the Redmine API key",
- "(you can use --key-file option as an alternative)") {|v| $api_key = v}
- opts.separator("")
- opts.separator("Options:")
- opts.on("-o", "--owner OWNER", "owner of the repository. using the rails login",
- "allows users to browse the repository within",
- "Redmine even for private projects. If you want to",
- "share repositories through Redmine.pm, you need",
- "to use the apache owner.") {|v| $svn_owner = v; $use_groupid = false}
- opts.on("-g", "--group GROUP", "group of the repository (default: root)") {|v| $svn_group = v; $use_groupid = false}
- opts.on("-u", "--url URL", "the base url Redmine will use to access your",
- "repositories. This option is used to register",
- "the repositories in Redmine automatically. 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 won't register",
- "the repositories in Redmine") {|v| $svn_url = v}
- opts.on( "--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") {|v| set_scm(v)}
- opts.on("-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.") {|v| $command = v}
- opts.on( "--key-file FILE", "path to a file that contains the Redmine API key",
- "(use this option instead of --key if you don't",
- "want the key to appear in the command line)") {|v| read_key_from_file(v)}
- opts.on("-t", "--test", "only show what should be done") {$test = true}
- opts.on("-f", "--force", "force repository creation even if the project", "repository is already declared in Redmine") {$force = true}
- opts.on("-v", "--verbose", "verbose") {$verbose += 1}
- opts.on("-V", "--version", "show version and exit") {puts Version; exit}
- opts.on("-h", "--help", "show help and exit") {puts opts; exit 1}
- opts.on("-q", "--quiet", "no log") {$quiet = true}
- opts.separator("")
- opts.separator("Examples:")
- opts.separator(" reposman.rb --svn-dir=/var/svn --redmine-host=redmine.host")
- opts.separator(" reposman.rb -s /var/git -r redmine.host -u http://git.host --scm git")
- opts.separator("")
- opts.separator("You can find more information on the redmine's wiki:\nhttp://www.redmine.org/projects/redmine/wiki/HowTos")
-
- opts.summary_width = 25
-end
-optparse.parse!
-
-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?)
- puts "Some arguments are missing. Use reposman.rb --help for getting help."
- exit 1
-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}"
- self.format = :xml
-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";
-
-begin
- # Get all active projects that have the Repository module enabled
- projects = Project.find(:all, :params => {:key => $api_key})
-rescue ActiveResource::ForbiddenAccess
- log("Request was denied by your Redmine server. Make sure that 'WS for repository management' is enabled in application settings and that you provided the correct 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 ? 0775 : 0770
- 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)
-
- if File.directory?(repos_path)
- # we must verify that repository has the good owner and the good
- # rights before leaving
- other_read = other_read_right?(repos_path)
- owner = owner_name(repos_path)
- next if project.is_public == other_read and owner == $svn_owner
-
- if $test
- log("\tchange mode on #{repos_path}")
- next
- end
-
- begin
- set_owner_and_rights(project, repos_path)
- rescue Errno::EPERM => e
- log("\tunable to change mode on #{repos_path} : #{e}\n")
- next
- end
-
- log("\tmode change on #{repos_path}");
-
- else
- # if repository is already declared in redmine, we don't create
- # unless user use -f with reposman
- if $force == false and project.respond_to?(:repository)
- log("\trepository for project #{project.identifier} already exists in Redmine", :level => 1)
- next
- end
-
- project.is_public ? File.umask(0002) : File.umask(0007)
-
- if $test
- log("\tcreate repository #{repos_path}")
- log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}") if $svn_url;
- next
- end
-
- begin
- set_owner_and_rights(project, repos_path) do
- if scm_module.nil?
- system_or_raise "#{$command} #{repos_path}"
- else
- scm_module.create(repos_path)
- end
- end
- rescue => e
- log("\tunable to create #{repos_path} : #{e}\n")
- next
- end
-
- if $svn_url
- begin
- project.post(:repository, :vendor => $scm, :repository => {:url => "#{$svn_url}#{project.identifier}"}, :key => $api_key)
- log("\trepository #{repos_path} registered in Redmine with url #{$svn_url}#{project.identifier}");
- rescue => e
- log("\trepository #{repos_path} not registered in Redmine: #{e.message}");
- end
- end
- log("\trepository #{repos_path} created");
- end
-end
diff --git a/trustie2/lib/.DS_Store b/trustie2/lib/.DS_Store
deleted file mode 100644
index ffee54fc3..000000000
Binary files a/trustie2/lib/.DS_Store and /dev/null differ
diff --git a/trustie2/lib/SVG/GPL.txt b/trustie2/lib/SVG/GPL.txt
deleted file mode 100644
index 0a1413473..000000000
--- a/trustie2/lib/SVG/GPL.txt
+++ /dev/null
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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 title 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.
-
-
- Copyright (C)
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
-
- , 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 Library General
-Public License instead of this License.
diff --git a/trustie2/lib/SVG/Graph/Bar.rb b/trustie2/lib/SVG/Graph/Bar.rb
deleted file mode 100644
index 695156594..000000000
--- a/trustie2/lib/SVG/Graph/Bar.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-require 'rexml/document'
-require 'SVG/Graph/Graph'
-require 'SVG/Graph/BarBase'
-
-module SVG
- module Graph
- # === Create presentation quality SVG bar graphs easily
- #
- # = Synopsis
- #
- # require 'SVG/Graph/Bar'
- #
- # fields = %w(Jan Feb Mar);
- # data_sales_02 = [12, 45, 21]
- #
- # graph = SVG::Graph::Bar.new(
- # :height => 500,
- # :width => 300,
- # :fields => fields
- # )
- #
- # graph.add_data(
- # :data => data_sales_02,
- # :title => 'Sales 2002'
- # )
- #
- # print "Content-type: image/svg+xml\r\n\r\n"
- # print graph.burn
- #
- # = Description
- #
- # This object aims to allow you to easily create high quality
- # SVG[http://www.w3c.org/tr/svg bar graphs. You can either use the default
- # style sheet or supply your own. Either way there are many options which
- # can be configured to give you control over how the graph is generated -
- # with or without a key, data elements at each point, title, subtitle etc.
- #
- # = Notes
- #
- # The default stylesheet handles upto 12 data sets, if you
- # use more you must create your own stylesheet and add the
- # additional settings for the extra data sets. You will know
- # if you go over 12 data sets as they will have no style and
- # be in black.
- #
- # = Examples
- #
- # * http://germane-software.com/repositories/public/SVG/test/test.rb
- #
- # = See also
- #
- # * SVG::Graph::Graph
- # * SVG::Graph::BarHorizontal
- # * SVG::Graph::Line
- # * SVG::Graph::Pie
- # * SVG::Graph::Plot
- # * SVG::Graph::TimeSeries
- class Bar < BarBase
- include REXML
-
- # See Graph::initialize and BarBase::set_defaults
- def set_defaults
- super
- self.top_align = self.top_font = 1
- end
-
- protected
-
- def get_x_labels
- @config[:fields]
- end
-
- def get_y_labels
- maxvalue = max_value
- minvalue = min_value
- range = maxvalue - minvalue
-
- top_pad = range == 0 ? 10 : range / 20.0
- scale_range = (maxvalue + top_pad) - minvalue
-
- scale_division = scale_divisions || (scale_range / 10.0)
-
- if scale_integers
- scale_division = scale_division < 1 ? 1 : scale_division.round
- end
-
- rv = []
- maxvalue = maxvalue%scale_division == 0 ?
- maxvalue : maxvalue + scale_division
- minvalue.step( maxvalue, scale_division ) {|v| rv << v}
- return rv
- end
-
- def x_label_offset( width )
- width / 2.0
- end
-
- def draw_data
- minvalue = min_value
- fieldwidth = field_width
-
- unit_size = (@graph_height.to_f - font_size*2*top_font) /
- (get_y_labels.max - get_y_labels.min)
- bargap = bar_gap ? (fieldwidth < 10 ? fieldwidth / 2 : 10) : 0
-
- bar_width = fieldwidth - bargap
- bar_width /= @data.length if stack == :side
- x_mod = (@graph_width-bargap)/2 - (stack==:side ? bar_width/2 : 0)
-
- bottom = @graph_height
-
- field_count = 0
- @config[:fields].each_index { |i|
- dataset_count = 0
- for dataset in @data
-
- # cases (assume 0 = +ve):
- # value min length
- # +ve +ve value - min
- # +ve -ve value - 0
- # -ve -ve value.abs - 0
-
- value = dataset[:data][i]
-
- left = (fieldwidth * field_count)
-
- length = (value.abs - (minvalue > 0 ? minvalue : 0)) * unit_size
- # top is 0 if value is negative
- top = bottom - (((value < 0 ? 0 : value) - minvalue) * unit_size)
- left += bar_width * dataset_count if stack == :side
-
- @graph.add_element( "rect", {
- "x" => left.to_s,
- "y" => top.to_s,
- "width" => bar_width.to_s,
- "height" => length.to_s,
- "class" => "fill#{dataset_count+1}"
- })
-
- make_datapoint_text(left + bar_width/2.0, top - 6, value.to_s)
- dataset_count += 1
- end
- field_count += 1
- }
- end
- end
- end
-end
diff --git a/trustie2/lib/SVG/Graph/BarBase.rb b/trustie2/lib/SVG/Graph/BarBase.rb
deleted file mode 100644
index 7b7dda887..000000000
--- a/trustie2/lib/SVG/Graph/BarBase.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-require 'rexml/document'
-require 'SVG/Graph/Graph'
-
-module SVG
- module Graph
- # = Synopsis
- #
- # A superclass for bar-style graphs. Do not attempt to instantiate
- # directly; use one of the subclasses instead.
- #
- # = Author
- #
- # Sean E. Russell
- #
- # Copyright 2004 Sean E. Russell
- # This software is available under the Ruby license[LICENSE.txt]
- #
- class BarBase < SVG::Graph::Graph
- # Ensures that :fields are provided in the configuration.
- def initialize config
- raise "fields was not supplied or is empty" unless config[:fields] &&
- config[:fields].kind_of?(Array) &&
- config[:fields].length > 0
- super
- end
-
- # In addition to the defaults set in Graph::initialize, sets
- # [bar_gap] true
- # [stack] :overlap
- def set_defaults
- init_with( :bar_gap => true, :stack => :overlap )
- end
-
- # Whether to have a gap between the bars or not, default
- # is true, set to false if you don't want gaps.
- attr_accessor :bar_gap
- # How to stack data sets. :overlap overlaps bars with
- # transparent colors, :top stacks bars on top of one another,
- # :side stacks the bars side-by-side. Defaults to :overlap.
- attr_accessor :stack
-
-
- protected
-
- def max_value
- @data.collect{|x| x[:data].max}.max
- end
-
- def min_value
- min = 0
- if min_scale_value.nil?
- min = @data.collect{|x| x[:data].min}.min
- min = min > 0 ? 0 : min
- else
- min = min_scale_value
- end
- return min
- end
-
- def get_css
- return < 500,
- # :width => 300,
- # :fields => fields,
- # })
- #
- # graph.add_data({
- # :data => data_sales_02,
- # :title => 'Sales 2002',
- # })
- #
- # print "Content-type: image/svg+xml\r\n\r\n"
- # print graph.burn
- #
- # = Description
- #
- # This object aims to allow you to easily create high quality
- # SVG horitonzal bar graphs. You can either use the default style sheet
- # or supply your own. Either way there are many options which can
- # be configured to give you control over how the graph is
- # generated - with or without a key, data elements at each point,
- # title, subtitle etc.
- #
- # = Examples
- #
- # * http://germane-software.com/repositories/public/SVG/test/test.rb
- #
- # = See also
- #
- # * SVG::Graph::Graph
- # * SVG::Graph::Bar
- # * SVG::Graph::Line
- # * SVG::Graph::Pie
- # * SVG::Graph::Plot
- # * SVG::Graph::TimeSeries
- #
- # == Author
- #
- # Sean E. Russell
- #
- # Copyright 2004 Sean E. Russell
- # This software is available under the Ruby license[LICENSE.txt]
- #
- class BarHorizontal < BarBase
- # In addition to the defaults set in BarBase::set_defaults, sets
- # [rotate_y_labels] true
- # [show_x_guidelines] true
- # [show_y_guidelines] false
- def set_defaults
- super
- init_with(
- :rotate_y_labels => true,
- :show_x_guidelines => true,
- :show_y_guidelines => false
- )
- self.right_align = self.right_font = 1
- end
-
- protected
-
- def get_x_labels
- maxvalue = max_value
- minvalue = min_value
- range = maxvalue - minvalue
- top_pad = range == 0 ? 10 : range / 20.0
- scale_range = (maxvalue + top_pad) - minvalue
-
- scale_division = scale_divisions || (scale_range / 10.0)
-
- if scale_integers
- scale_division = scale_division < 1 ? 1 : scale_division.round
- end
-
- rv = []
- maxvalue = maxvalue%scale_division == 0 ?
- maxvalue : maxvalue + scale_division
- minvalue.step( maxvalue, scale_division ) {|v| rv << v}
- return rv
- end
-
- def get_y_labels
- @config[:fields]
- end
-
- def y_label_offset( height )
- height / -2.0
- end
-
- def draw_data
- minvalue = min_value
- fieldheight = field_height
-
- unit_size = (@graph_width.to_f - font_size*2*right_font ) /
- (get_x_labels.max - get_x_labels.min )
- bargap = bar_gap ? (fieldheight < 10 ? fieldheight / 2 : 10) : 0
-
- bar_height = fieldheight - bargap
- bar_height /= @data.length if stack == :side
- y_mod = (bar_height / 2) + (font_size / 2)
-
- field_count = 1
- @config[:fields].each_index { |i|
- dataset_count = 0
- for dataset in @data
- value = dataset[:data][i]
-
- top = @graph_height - (fieldheight * field_count)
- top += (bar_height * dataset_count) if stack == :side
- # cases (assume 0 = +ve):
- # value min length left
- # +ve +ve value.abs - min minvalue.abs
- # +ve -ve value.abs - 0 minvalue.abs
- # -ve -ve value.abs - 0 minvalue.abs + value
- length = (value.abs - (minvalue > 0 ? minvalue : 0)) * unit_size
- left = (minvalue.abs + (value < 0 ? value : 0)) * unit_size
-
- @graph.add_element( "rect", {
- "x" => left.to_s,
- "y" => top.to_s,
- "width" => length.to_s,
- "height" => bar_height.to_s,
- "class" => "fill#{dataset_count+1}"
- })
-
- make_datapoint_text(
- left+length+5, top+y_mod, value, "text-anchor: start; "
- )
- dataset_count += 1
- end
- field_count += 1
- }
- end
- end
- end
-end
diff --git a/trustie2/lib/SVG/Graph/Graph.rb b/trustie2/lib/SVG/Graph/Graph.rb
deleted file mode 100644
index 8a840b2f1..000000000
--- a/trustie2/lib/SVG/Graph/Graph.rb
+++ /dev/null
@@ -1,978 +0,0 @@
-begin
- require 'zlib'
- @@__have_zlib = true
-rescue
- @@__have_zlib = false
-end
-
-require 'rexml/document'
-
-module SVG
- module Graph
- VERSION = '@ANT_VERSION@'
-
- # === Base object for generating SVG Graphs
- #
- # == Synopsis
- #
- # This class is only used as a superclass of specialized charts. Do not
- # attempt to use this class directly, unless creating a new chart type.
- #
- # For examples of how to subclass this class, see the existing specific
- # subclasses, such as SVG::Graph::Pie.
- #
- # == Examples
- #
- # For examples of how to use this package, see either the test files, or
- # the documentation for the specific class you want to use.
- #
- # * file:test/plot.rb
- # * file:test/single.rb
- # * file:test/test.rb
- # * file:test/timeseries.rb
- #
- # == Description
- #
- # This package should be used as a base for creating SVG graphs.
- #
- # == Acknowledgements
- #
- # Leo Lapworth for creating the SVG::TT::Graph package which this Ruby
- # port is based on.
- #
- # Stephen Morgan for creating the TT template and SVG.
- #
- # == See
- #
- # * SVG::Graph::BarHorizontal
- # * SVG::Graph::Bar
- # * SVG::Graph::Line
- # * SVG::Graph::Pie
- # * SVG::Graph::Plot
- # * SVG::Graph::TimeSeries
- #
- # == Author
- #
- # Sean E. Russell
- #
- # Copyright 2004 Sean E. Russell
- # This software is available under the Ruby license[LICENSE.txt]
- #
- class Graph
- include REXML
-
- # Initialize the graph object with the graph settings. You won't
- # instantiate this class directly; see the subclass for options.
- # [width] 500
- # [height] 300
- # [show_x_guidelines] false
- # [show_y_guidelines] true
- # [show_data_values] true
- # [min_scale_value] 0
- # [show_x_labels] true
- # [stagger_x_labels] false
- # [rotate_x_labels] false
- # [step_x_labels] 1
- # [step_include_first_x_label] true
- # [show_y_labels] true
- # [rotate_y_labels] false
- # [scale_integers] false
- # [show_x_title] false
- # [x_title] 'X Field names'
- # [show_y_title] false
- # [y_title_text_direction] :bt
- # [y_title] 'Y Scale'
- # [show_graph_title] false
- # [graph_title] 'Graph Title'
- # [show_graph_subtitle] false
- # [graph_subtitle] 'Graph Sub Title'
- # [key] true,
- # [key_position] :right, # bottom or righ
- # [font_size] 12
- # [title_font_size] 16
- # [subtitle_font_size] 14
- # [x_label_font_size] 12
- # [x_title_font_size] 14
- # [y_label_font_size] 12
- # [y_title_font_size] 14
- # [key_font_size] 10
- # [no_css] false
- # [add_popups] false
- def initialize( config )
- @config = config
-
- self.top_align = self.top_font = self.right_align = self.right_font = 0
-
- init_with({
- :width => 500,
- :height => 300,
- :show_x_guidelines => false,
- :show_y_guidelines => true,
- :show_data_values => true,
-
-# :min_scale_value => 0,
-
- :show_x_labels => true,
- :stagger_x_labels => false,
- :rotate_x_labels => false,
- :step_x_labels => 1,
- :step_include_first_x_label => true,
-
- :show_y_labels => true,
- :rotate_y_labels => false,
- :stagger_y_labels => false,
- :scale_integers => false,
-
- :show_x_title => false,
- :x_title => 'X Field names',
-
- :show_y_title => false,
- :y_title_text_direction => :bt,
- :y_title => 'Y Scale',
-
- :show_graph_title => false,
- :graph_title => 'Graph Title',
- :show_graph_subtitle => false,
- :graph_subtitle => 'Graph Sub Title',
- :key => true,
- :key_position => :right, # bottom or right
-
- :font_size =>12,
- :title_font_size =>16,
- :subtitle_font_size =>14,
- :x_label_font_size =>12,
- :x_title_font_size =>14,
- :y_label_font_size =>12,
- :y_title_font_size =>14,
- :key_font_size =>10,
-
- :no_css =>false,
- :add_popups =>false,
- })
-
- set_defaults if respond_to? :set_defaults
-
- init_with config
- end
-
-
- # This method allows you do add data to the graph object.
- # It can be called several times to add more data sets in.
- #
- # data_sales_02 = [12, 45, 21];
- #
- # graph.add_data({
- # :data => data_sales_02,
- # :title => 'Sales 2002'
- # })
- def add_data conf
- @data = [] unless defined? @data
-
- if conf[:data] and conf[:data].kind_of? Array
- @data << conf
- else
- raise "No data provided by #{conf.inspect}"
- end
- end
-
-
- # This method removes all data from the object so that you can
- # reuse it to create a new graph but with the same config options.
- #
- # graph.clear_data
- def clear_data
- @data = []
- end
-
-
- # This method processes the template with the data and
- # config which has been set and returns the resulting SVG.
- #
- # This method will croak unless at least one data set has
- # been added to the graph object.
- #
- # print graph.burn
- def burn
- raise "No data available" unless @data.size > 0
-
- calculations if respond_to? :calculations
-
- start_svg
- calculate_graph_dimensions
- @foreground = Element.new( "g" )
- draw_graph
- draw_titles
- draw_legend
- draw_data
- @graph.add_element( @foreground )
- style
-
- data = ""
- @doc.write( data, 0 )
-
- if @config[:compress]
- if @@__have_zlib
- inp, out = IO.pipe
- gz = Zlib::GzipWriter.new( out )
- gz.write data
- gz.close
- data = inp.read
- else
- data << "";
- end
- end
-
- return data
- end
-
-
- # Set the height of the graph box, this is the total height
- # of the SVG box created - not the graph it self which auto
- # scales to fix the space.
- attr_accessor :height
- # Set the width of the graph box, this is the total width
- # of the SVG box created - not the graph it self which auto
- # scales to fix the space.
- attr_accessor :width
- # Set the path to an external stylesheet, set to '' if
- # you want to revert back to using the defaut internal version.
- #
- # To create an external stylesheet create a graph using the
- # default internal version and copy the stylesheet section to
- # an external file and edit from there.
- attr_accessor :style_sheet
- # (Bool) Show the value of each element of data on the graph
- attr_accessor :show_data_values
- # The point at which the Y axis starts, defaults to '0',
- # if set to nil it will default to the minimum data value.
- attr_accessor :min_scale_value
- # Whether to show labels on the X axis or not, defaults
- # to true, set to false if you want to turn them off.
- attr_accessor :show_x_labels
- # This puts the X labels at alternative levels so if they
- # are long field names they will not overlap so easily.
- # Default it false, to turn on set to true.
- attr_accessor :stagger_x_labels
- # This puts the Y labels at alternative levels so if they
- # are long field names they will not overlap so easily.
- # Default it false, to turn on set to true.
- attr_accessor :stagger_y_labels
- # This turns the X axis labels by 90 degrees.
- # Default it false, to turn on set to true.
- attr_accessor :rotate_x_labels
- # This turns the Y axis labels by 90 degrees.
- # Default it false, to turn on set to true.
- attr_accessor :rotate_y_labels
- # How many "steps" to use between displayed X axis labels,
- # a step of one means display every label, a step of two results
- # in every other label being displayed (label label label),
- # a step of three results in every third label being displayed
- # (label label label) and so on.
- attr_accessor :step_x_labels
- # Whether to (when taking "steps" between X axis labels) step from
- # the first label (i.e. always include the first label) or step from
- # the X axis origin (i.e. start with a gap if step_x_labels is greater
- # than one).
- attr_accessor :step_include_first_x_label
- # Whether to show labels on the Y axis or not, defaults
- # to true, set to false if you want to turn them off.
- attr_accessor :show_y_labels
- # Ensures only whole numbers are used as the scale divisions.
- # Default it false, to turn on set to true. This has no effect if
- # scale divisions are less than 1.
- attr_accessor :scale_integers
- # This defines the gap between markers on the Y axis,
- # default is a 10th of the max_value, e.g. you will have
- # 10 markers on the Y axis. NOTE: do not set this too
- # low - you are limited to 999 markers, after that the
- # graph won't generate.
- attr_accessor :scale_divisions
- # Whether to show the title under the X axis labels,
- # default is false, set to true to show.
- attr_accessor :show_x_title
- # What the title under X axis should be, e.g. 'Months'.
- attr_accessor :x_title
- # Whether to show the title under the Y axis labels,
- # default is false, set to true to show.
- attr_accessor :show_y_title
- # Aligns writing mode for Y axis label.
- # Defaults to :bt (Bottom to Top).
- # Change to :tb (Top to Bottom) to reverse.
- attr_accessor :y_title_text_direction
- # What the title under Y axis should be, e.g. 'Sales in thousands'.
- attr_accessor :y_title
- # Whether to show a title on the graph, defaults
- # to false, set to true to show.
- attr_accessor :show_graph_title
- # What the title on the graph should be.
- attr_accessor :graph_title
- # Whether to show a subtitle on the graph, defaults
- # to false, set to true to show.
- attr_accessor :show_graph_subtitle
- # What the subtitle on the graph should be.
- attr_accessor :graph_subtitle
- # Whether to show a key, defaults to false, set to
- # true if you want to show it.
- attr_accessor :key
- # Where the key should be positioned, defaults to
- # :right, set to :bottom if you want to move it.
- attr_accessor :key_position
- # Set the font size (in points) of the data point labels
- attr_accessor :font_size
- # Set the font size of the X axis labels
- attr_accessor :x_label_font_size
- # Set the font size of the X axis title
- attr_accessor :x_title_font_size
- # Set the font size of the Y axis labels
- attr_accessor :y_label_font_size
- # Set the font size of the Y axis title
- attr_accessor :y_title_font_size
- # Set the title font size
- attr_accessor :title_font_size
- # Set the subtitle font size
- attr_accessor :subtitle_font_size
- # Set the key font size
- attr_accessor :key_font_size
- # Show guidelines for the X axis
- attr_accessor :show_x_guidelines
- # Show guidelines for the Y axis
- attr_accessor :show_y_guidelines
- # Do not use CSS if set to true. Many SVG viewers do not support CSS, but
- # not using CSS can result in larger SVGs as well as making it impossible to
- # change colors after the chart is generated. Defaults to false.
- attr_accessor :no_css
- # Add popups for the data points on some graphs
- attr_accessor :add_popups
-
-
- protected
-
- def sort( *arrys )
- sort_multiple( arrys )
- end
-
- # Overwrite configuration options with supplied options. Used
- # by subclasses.
- def init_with config
- config.each { |key, value|
- self.send((key.to_s+"=").to_sym, value ) if respond_to? key.to_sym
- }
- end
-
- attr_accessor :top_align, :top_font, :right_align, :right_font
-
- KEY_BOX_SIZE = 12
-
- # Override this (and call super) to change the margin to the left
- # of the plot area. Results in @border_left being set.
- def calculate_left_margin
- @border_left = 7
- # Check for Y labels
- max_y_label_height_px = rotate_y_labels ?
- y_label_font_size :
- get_y_labels.max{|a,b|
- a.to_s.length<=>b.to_s.length
- }.to_s.length * y_label_font_size * 0.6
- @border_left += max_y_label_height_px if show_y_labels
- @border_left += max_y_label_height_px + 10 if stagger_y_labels
- @border_left += y_title_font_size + 5 if show_y_title
- end
-
-
- # Calculates the width of the widest Y label. This will be the
- # character height if the Y labels are rotated
- def max_y_label_width_px
- return font_size if rotate_y_labels
- end
-
-
- # Override this (and call super) to change the margin to the right
- # of the plot area. Results in @border_right being set.
- def calculate_right_margin
- @border_right = 7
- if key and key_position == :right
- val = keys.max { |a,b| a.length <=> b.length }
- @border_right += val.length * key_font_size * 0.6
- @border_right += KEY_BOX_SIZE
- @border_right += 10 # Some padding around the box
- end
- end
-
-
- # Override this (and call super) to change the margin to the top
- # of the plot area. Results in @border_top being set.
- def calculate_top_margin
- @border_top = 5
- @border_top += title_font_size if show_graph_title
- @border_top += 5
- @border_top += subtitle_font_size if show_graph_subtitle
- end
-
-
- # Adds pop-up point information to a graph.
- def add_popup( x, y, label )
- txt_width = label.length * font_size * 0.6 + 10
- tx = (x+txt_width > width ? x-5 : x+5)
- t = @foreground.add_element( "text", {
- "x" => tx.to_s,
- "y" => (y - font_size).to_s,
- "visibility" => "hidden",
- })
- t.attributes["style"] = "fill: #000; "+
- (x+txt_width > width ? "text-anchor: end;" : "text-anchor: start;")
- t.text = label.to_s
- t.attributes["id"] = t.object_id.to_s
-
- @foreground.add_element( "circle", {
- "cx" => x.to_s,
- "cy" => y.to_s,
- "r" => "10",
- "style" => "opacity: 0",
- "onmouseover" =>
- "document.getElementById(#{t.object_id}).setAttribute('visibility', 'visible' )",
- "onmouseout" =>
- "document.getElementById(#{t.object_id}).setAttribute('visibility', 'hidden' )",
- })
-
- end
-
-
- # Override this (and call super) to change the margin to the bottom
- # of the plot area. Results in @border_bottom being set.
- def calculate_bottom_margin
- @border_bottom = 7
- if key and key_position == :bottom
- @border_bottom += @data.size * (font_size + 5)
- @border_bottom += 10
- end
- if show_x_labels
- max_x_label_height_px = (not rotate_x_labels) ?
- x_label_font_size :
- get_x_labels.max{|a,b|
- a.to_s.length<=>b.to_s.length
- }.to_s.length * x_label_font_size * 0.6
- @border_bottom += max_x_label_height_px
- @border_bottom += max_x_label_height_px + 10 if stagger_x_labels
- end
- @border_bottom += x_title_font_size + 5 if show_x_title
- end
-
-
- # Draws the background, axis, and labels.
- def draw_graph
- @graph = @root.add_element( "g", {
- "transform" => "translate( #@border_left #@border_top )"
- })
-
- # Background
- @graph.add_element( "rect", {
- "x" => "0",
- "y" => "0",
- "width" => @graph_width.to_s,
- "height" => @graph_height.to_s,
- "class" => "graphBackground"
- })
-
- # Axis
- @graph.add_element( "path", {
- "d" => "M 0 0 v#@graph_height",
- "class" => "axis",
- "id" => "xAxis"
- })
- @graph.add_element( "path", {
- "d" => "M 0 #@graph_height h#@graph_width",
- "class" => "axis",
- "id" => "yAxis"
- })
-
- draw_x_labels
- draw_y_labels
- end
-
-
- # Where in the X area the label is drawn
- # Centered in the field, should be width/2. Start, 0.
- def x_label_offset( width )
- 0
- end
-
- def make_datapoint_text( x, y, value, style="" )
- if show_data_values
- @foreground.add_element( "text", {
- "x" => x.to_s,
- "y" => y.to_s,
- "class" => "dataPointLabel",
- "style" => "#{style} stroke: #fff; stroke-width: 2;"
- }).text = value.to_s
- text = @foreground.add_element( "text", {
- "x" => x.to_s,
- "y" => y.to_s,
- "class" => "dataPointLabel"
- })
- text.text = value.to_s
- text.attributes["style"] = style if style.length > 0
- end
- end
-
-
- # Draws the X axis labels
- def draw_x_labels
- stagger = x_label_font_size + 5
- if show_x_labels
- label_width = field_width
-
- count = 0
- for label in get_x_labels
- if step_include_first_x_label == true then
- step = count % step_x_labels
- else
- step = (count + 1) % step_x_labels
- end
-
- if step == 0 then
- text = @graph.add_element( "text" )
- text.attributes["class"] = "xAxisLabels"
- text.text = label.to_s
-
- x = count * label_width + x_label_offset( label_width )
- y = @graph_height + x_label_font_size + 3
- t = 0 - (font_size / 2)
-
- if stagger_x_labels and count % 2 == 1
- y += stagger
- @graph.add_element( "path", {
- "d" => "M#{x} #@graph_height v#{stagger}",
- "class" => "staggerGuideLine"
- })
- end
-
- text.attributes["x"] = x.to_s
- text.attributes["y"] = y.to_s
- if rotate_x_labels
- text.attributes["transform"] =
- "rotate( 90 #{x} #{y-x_label_font_size} )"+
- " translate( 0 -#{x_label_font_size/4} )"
- text.attributes["style"] = "text-anchor: start"
- else
- text.attributes["style"] = "text-anchor: middle"
- end
- end
-
- draw_x_guidelines( label_width, count ) if show_x_guidelines
- count += 1
- end
- end
- end
-
-
- # Where in the Y area the label is drawn
- # Centered in the field, should be width/2. Start, 0.
- def y_label_offset( height )
- 0
- end
-
-
- def field_width
- (@graph_width.to_f - font_size*2*right_font) /
- (get_x_labels.length - right_align)
- end
-
-
- def field_height
- (@graph_height.to_f - font_size*2*top_font) /
- (get_y_labels.length - top_align)
- end
-
-
- # Draws the Y axis labels
- def draw_y_labels
- stagger = y_label_font_size + 5
- if show_y_labels
- label_height = field_height
-
- count = 0
- y_offset = @graph_height + y_label_offset( label_height )
- y_offset += font_size/1.2 unless rotate_y_labels
- for label in get_y_labels
- y = y_offset - (label_height * count)
- x = rotate_y_labels ? 0 : -3
-
- if stagger_y_labels and count % 2 == 1
- x -= stagger
- @graph.add_element( "path", {
- "d" => "M#{x} #{y} h#{stagger}",
- "class" => "staggerGuideLine"
- })
- end
-
- text = @graph.add_element( "text", {
- "x" => x.to_s,
- "y" => y.to_s,
- "class" => "yAxisLabels"
- })
- text.text = label.to_s
- if rotate_y_labels
- text.attributes["transform"] = "translate( -#{font_size} 0 ) "+
- "rotate( 90 #{x} #{y} ) "
- text.attributes["style"] = "text-anchor: middle"
- else
- text.attributes["y"] = (y - (y_label_font_size/2)).to_s
- text.attributes["style"] = "text-anchor: end"
- end
- draw_y_guidelines( label_height, count ) if show_y_guidelines
- count += 1
- end
- end
- end
-
-
- # Draws the X axis guidelines
- def draw_x_guidelines( label_height, count )
- if count != 0
- @graph.add_element( "path", {
- "d" => "M#{label_height*count} 0 v#@graph_height",
- "class" => "guideLines"
- })
- end
- end
-
-
- # Draws the Y axis guidelines
- def draw_y_guidelines( label_height, count )
- if count != 0
- @graph.add_element( "path", {
- "d" => "M0 #{@graph_height-(label_height*count)} h#@graph_width",
- "class" => "guideLines"
- })
- end
- end
-
-
- # Draws the graph title and subtitle
- def draw_titles
- if show_graph_title
- @root.add_element( "text", {
- "x" => (width / 2).to_s,
- "y" => (title_font_size).to_s,
- "class" => "mainTitle"
- }).text = graph_title.to_s
- end
-
- if show_graph_subtitle
- y_subtitle = show_graph_title ?
- title_font_size + 10 :
- subtitle_font_size
- @root.add_element("text", {
- "x" => (width / 2).to_s,
- "y" => (y_subtitle).to_s,
- "class" => "subTitle"
- }).text = graph_subtitle.to_s
- end
-
- if show_x_title
- y = @graph_height + @border_top + x_title_font_size
- if show_x_labels
- y += x_label_font_size + 5 if stagger_x_labels
- y += x_label_font_size + 5
- end
- x = width / 2
-
- @root.add_element("text", {
- "x" => x.to_s,
- "y" => y.to_s,
- "class" => "xAxisTitle",
- }).text = x_title.to_s
- end
-
- if show_y_title
- x = y_title_font_size + (y_title_text_direction==:bt ? 3 : -3)
- y = height / 2
-
- text = @root.add_element("text", {
- "x" => x.to_s,
- "y" => y.to_s,
- "class" => "yAxisTitle",
- })
- text.text = y_title.to_s
- if y_title_text_direction == :bt
- text.attributes["transform"] = "rotate( -90, #{x}, #{y} )"
- else
- text.attributes["transform"] = "rotate( 90, #{x}, #{y} )"
- end
- end
- end
-
- def keys
- return @data.collect{ |d| d[:title] }
- end
-
- # Draws the legend on the graph
- def draw_legend
- if key
- group = @root.add_element( "g" )
-
- key_count = 0
- for key_name in keys
- y_offset = (KEY_BOX_SIZE * key_count) + (key_count * 5)
- group.add_element( "rect", {
- "x" => 0.to_s,
- "y" => y_offset.to_s,
- "width" => KEY_BOX_SIZE.to_s,
- "height" => KEY_BOX_SIZE.to_s,
- "class" => "key#{key_count+1}"
- })
- group.add_element( "text", {
- "x" => (KEY_BOX_SIZE + 5).to_s,
- "y" => (y_offset + KEY_BOX_SIZE).to_s,
- "class" => "keyText"
- }).text = key_name.to_s
- key_count += 1
- end
-
- case key_position
- when :right
- x_offset = @graph_width + @border_left + 10
- y_offset = @border_top + 20
- when :bottom
- x_offset = @border_left + 20
- y_offset = @border_top + @graph_height + 5
- if show_x_labels
- max_x_label_height_px = (not rotate_x_labels) ?
- x_label_font_size :
- get_x_labels.max{|a,b|
- a.to_s.length<=>b.to_s.length
- }.to_s.length * x_label_font_size * 0.6
- x_label_font_size
- y_offset += max_x_label_height_px
- y_offset += max_x_label_height_px + 5 if stagger_x_labels
- end
- y_offset += x_title_font_size + 5 if show_x_title
- end
- group.attributes["transform"] = "translate(#{x_offset} #{y_offset})"
- end
- end
-
-
- private
-
- def sort_multiple( arrys, lo=0, hi=arrys[0].length-1 )
- if lo < hi
- p = partition(arrys,lo,hi)
- sort_multiple(arrys, lo, p-1)
- sort_multiple(arrys, p+1, hi)
- end
- arrys
- end
-
- def partition( arrys, lo, hi )
- p = arrys[0][lo]
- l = lo
- z = lo+1
- while z <= hi
- if arrys[0][z] < p
- l += 1
- arrys.each { |arry| arry[z], arry[l] = arry[l], arry[z] }
- end
- z += 1
- end
- arrys.each { |arry| arry[lo], arry[l] = arry[l], arry[lo] }
- l
- end
-
- def style
- if no_css
- styles = parse_css
- @root.elements.each("//*[@class]") { |el|
- cl = el.attributes["class"]
- style = styles[cl]
- style += el.attributes["style"] if el.attributes["style"]
- el.attributes["style"] = style
- }
- end
- end
-
- def parse_css
- css = get_style
- rv = {}
- while css =~ /^(\.(\w+)(?:\s*,\s*\.\w+)*)\s*\{/m
- names_orig = names = $1
- css = $'
- css =~ /([^}]+)\}/m
- content = $1
- css = $'
-
- nms = []
- while names =~ /^\s*,?\s*\.(\w+)/
- nms << $1
- names = $'
- end
-
- content = content.tr( "\n\t", " ")
- for name in nms
- current = rv[name]
- current = current ? current+"; "+content : content
- rv[name] = current.strip.squeeze(" ")
- end
- end
- return rv
- end
-
-
- # Override and place code to add defs here
- def add_defs defs
- end
-
-
- def start_svg
- # Base document
- @doc = Document.new
- @doc << XMLDecl.new
- @doc << DocType.new( %q{svg PUBLIC "-//W3C//DTD SVG 1.0//EN" } +
- %q{"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"} )
- if style_sheet && style_sheet != ''
- @doc << Instruction.new( "xml-stylesheet",
- %Q{href="#{style_sheet}" type="text/css"} )
- end
- @root = @doc.add_element( "svg", {
- "width" => width.to_s,
- "height" => height.to_s,
- "viewBox" => "0 0 #{width} #{height}",
- "xmlns" => "http://www.w3.org/2000/svg",
- "xmlns:xlink" => "http://www.w3.org/1999/xlink",
- "xmlns:a3" => "http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/",
- "a3:scriptImplementation" => "Adobe"
- })
- @root << Comment.new( " "+"\\"*66 )
- @root << Comment.new( " Created with SVG::Graph " )
- @root << Comment.new( " SVG::Graph by Sean E. Russell " )
- @root << Comment.new( " Losely based on SVG::TT::Graph for Perl by"+
- " Leo Lapworth & Stephan Morgan " )
- @root << Comment.new( " "+"/"*66 )
-
- defs = @root.add_element( "defs" )
- add_defs defs
- if not(style_sheet && style_sheet != '') and !no_css
- @root << Comment.new(" include default stylesheet if none specified ")
- style = defs.add_element( "style", {"type"=>"text/css"} )
- style << CData.new( get_style )
- end
-
- @root << Comment.new( "SVG Background" )
- @root.add_element( "rect", {
- "width" => width.to_s,
- "height" => height.to_s,
- "x" => "0",
- "y" => "0",
- "class" => "svgBackground"
- })
- end
-
-
- def calculate_graph_dimensions
- calculate_left_margin
- calculate_right_margin
- calculate_bottom_margin
- calculate_top_margin
- @graph_width = width - @border_left - @border_right
- @graph_height = height - @border_top - @border_bottom
- end
-
- def get_style
- return < 500,
- # :width => 300,
- # :fields => fields,
- # })
- #
- # graph.add_data({
- # :data => data_sales_02,
- # :title => 'Sales 2002',
- # })
- #
- # graph.add_data({
- # :data => data_sales_03,
- # :title => 'Sales 2003',
- # })
- #
- # print "Content-type: image/svg+xml\r\n\r\n";
- # print graph.burn();
- #
- # = Description
- #
- # This object aims to allow you to easily create high quality
- # SVG line graphs. You can either use the default style sheet
- # or supply your own. Either way there are many options which can
- # be configured to give you control over how the graph is
- # generated - with or without a key, data elements at each point,
- # title, subtitle etc.
- #
- # = Examples
- #
- # http://www.germane-software/repositories/public/SVG/test/single.rb
- #
- # = Notes
- #
- # The default stylesheet handles upto 10 data sets, if you
- # use more you must create your own stylesheet and add the
- # additional settings for the extra data sets. You will know
- # if you go over 10 data sets as they will have no style and
- # be in black.
- #
- # = See also
- #
- # * SVG::Graph::Graph
- # * SVG::Graph::BarHorizontal
- # * SVG::Graph::Bar
- # * SVG::Graph::Pie
- # * SVG::Graph::Plot
- # * SVG::Graph::TimeSeries
- #
- # == Author
- #
- # Sean E. Russell
- #
- # Copyright 2004 Sean E. Russell
- # This software is available under the Ruby license[LICENSE.txt]
- #
- class Line < SVG::Graph::Graph
- # Show a small circle on the graph where the line
- # goes from one point to the next.
- attr_accessor :show_data_points
- # Accumulates each data set. (i.e. Each point increased by sum of
- # all previous series at same point). Default is 0, set to '1' to show.
- attr_accessor :stacked
- # Fill in the area under the plot if true
- attr_accessor :area_fill
-
- # The constructor takes a hash reference, fields (the names for each
- # field on the X axis) MUST be set, all other values are defaulted to
- # those shown above - with the exception of style_sheet which defaults
- # to using the internal style sheet.
- def initialize config
- raise "fields was not supplied or is empty" unless config[:fields] &&
- config[:fields].kind_of?(Array) &&
- config[:fields].length > 0
- super
- end
-
- # In addition to the defaults set in Graph::initialize, sets
- # [show_data_points] true
- # [show_data_values] true
- # [stacked] false
- # [area_fill] false
- def set_defaults
- init_with(
- :show_data_points => true,
- :show_data_values => true,
- :stacked => false,
- :area_fill => false
- )
-
- self.top_align = self.top_font = self.right_align = self.right_font = 1
- end
-
- protected
-
- def max_value
- max = 0
-
- if (stacked == true) then
- sums = Array.new(@config[:fields].length).fill(0)
-
- @data.each do |data|
- sums.each_index do |i|
- sums[i] += data[:data][i].to_f
- end
- end
-
- max = sums.max
- else
- max = @data.collect{|x| x[:data].max}.max
- end
-
- return max
- end
-
- def min_value
- min = 0
-
- if (min_scale_value.nil? == false) then
- min = min_scale_value
- elsif (stacked == true) then
- min = @data[-1][:data].min
- else
- min = @data.collect{|x| x[:data].min}.min
- end
-
- return min
- end
-
- def get_x_labels
- @config[:fields]
- end
-
- def calculate_left_margin
- super
- label_left = @config[:fields][0].length / 2 * font_size * 0.6
- @border_left = label_left if label_left > @border_left
- end
-
- def get_y_labels
- maxvalue = max_value
- minvalue = min_value
- range = maxvalue - minvalue
- top_pad = range == 0 ? 10 : range / 20.0
- scale_range = (maxvalue + top_pad) - minvalue
-
- scale_division = scale_divisions || (scale_range / 10.0)
-
- if scale_integers
- scale_division = scale_division < 1 ? 1 : scale_division.round
- end
-
- rv = []
- maxvalue = maxvalue%scale_division == 0 ?
- maxvalue : maxvalue + scale_division
- minvalue.step( maxvalue, scale_division ) {|v| rv << v}
- return rv
- end
-
- def calc_coords(field, value, width = field_width, height = field_height)
- coords = {:x => 0, :y => 0}
- coords[:x] = width * field
- coords[:y] = @graph_height - value * height
-
- return coords
- end
-
- def draw_data
- minvalue = min_value
- fieldheight = (@graph_height.to_f - font_size*2*top_font) /
- (get_y_labels.max - get_y_labels.min)
- fieldwidth = field_width
- line = @data.length
-
- prev_sum = Array.new(@config[:fields].length).fill(0)
- cum_sum = Array.new(@config[:fields].length).fill(-minvalue)
-
- for data in @data.reverse
- lpath = ""
- apath = ""
-
- if not stacked then cum_sum.fill(-minvalue) end
-
- data[:data].each_index do |i|
- cum_sum[i] += data[:data][i]
-
- c = calc_coords(i, cum_sum[i], fieldwidth, fieldheight)
-
- lpath << "#{c[:x]} #{c[:y]} "
- end
-
- if area_fill
- if stacked then
- (prev_sum.length - 1).downto 0 do |i|
- c = calc_coords(i, prev_sum[i], fieldwidth, fieldheight)
-
- apath << "#{c[:x]} #{c[:y]} "
- end
-
- c = calc_coords(0, prev_sum[0], fieldwidth, fieldheight)
- else
- apath = "V#@graph_height"
- c = calc_coords(0, 0, fieldwidth, fieldheight)
- end
-
- @graph.add_element("path", {
- "d" => "M#{c[:x]} #{c[:y]} L" + lpath + apath + "Z",
- "class" => "fill#{line}"
- })
- end
-
- @graph.add_element("path", {
- "d" => "M0 #@graph_height L" + lpath,
- "class" => "line#{line}"
- })
-
- if show_data_points || show_data_values
- cum_sum.each_index do |i|
- if show_data_points
- @graph.add_element( "circle", {
- "cx" => (fieldwidth * i).to_s,
- "cy" => (@graph_height - cum_sum[i] * fieldheight).to_s,
- "r" => "2.5",
- "class" => "dataPoint#{line}"
- })
- end
- make_datapoint_text(
- fieldwidth * i,
- @graph_height - cum_sum[i] * fieldheight - 6,
- cum_sum[i] + minvalue
- )
- end
- end
-
- prev_sum = cum_sum.dup
- line -= 1
- end
- end
-
-
- def get_css
- return < 500,
- # :width => 300,
- # :fields => fields,
- # })
- #
- # graph.add_data({
- # :data => data_sales_02,
- # :title => 'Sales 2002',
- # })
- #
- # print "Content-type: image/svg+xml\r\n\r\n"
- # print graph.burn();
- #
- # == Description
- #
- # This object aims to allow you to easily create high quality
- # SVG pie graphs. You can either use the default style sheet
- # or supply your own. Either way there are many options which can
- # be configured to give you control over how the graph is
- # generated - with or without a key, display percent on pie chart,
- # title, subtitle etc.
- #
- # = Examples
- #
- # http://www.germane-software/repositories/public/SVG/test/single.rb
- #
- # == See also
- #
- # * SVG::Graph::Graph
- # * SVG::Graph::BarHorizontal
- # * SVG::Graph::Bar
- # * SVG::Graph::Line
- # * SVG::Graph::Plot
- # * SVG::Graph::TimeSeries
- #
- # == Author
- #
- # Sean E. Russell
- #
- # Copyright 2004 Sean E. Russell
- # This software is available under the Ruby license[LICENSE.txt]
- #
- class Pie < Graph
- # Defaults are those set by Graph::initialize, and
- # [show_shadow] true
- # [shadow_offset] 10
- # [show_data_labels] false
- # [show_actual_values] false
- # [show_percent] true
- # [show_key_data_labels] true
- # [show_key_actual_values] true
- # [show_key_percent] false
- # [expanded] false
- # [expand_greatest] false
- # [expand_gap] 10
- # [show_x_labels] false
- # [show_y_labels] false
- # [datapoint_font_size] 12
- def set_defaults
- init_with(
- :show_shadow => true,
- :shadow_offset => 10,
-
- :show_data_labels => false,
- :show_actual_values => false,
- :show_percent => true,
-
- :show_key_data_labels => true,
- :show_key_actual_values => true,
- :show_key_percent => false,
-
- :expanded => false,
- :expand_greatest => false,
- :expand_gap => 10,
-
- :show_x_labels => false,
- :show_y_labels => false,
- :datapoint_font_size => 12
- )
- @data = []
- end
-
- # Adds a data set to the graph.
- #
- # graph.add_data( { :data => [1,2,3,4] } )
- #
- # Note that the :title is not necessary. If multiple
- # data sets are added to the graph, the pie chart will
- # display the +sums+ of the data. EG:
- #
- # graph.add_data( { :data => [1,2,3,4] } )
- # graph.add_data( { :data => [2,3,5,9] } )
- #
- # is the same as:
- #
- # graph.add_data( { :data => [3,5,8,13] } )
- def add_data arg
- arg[:data].each_index {|idx|
- @data[idx] = 0 unless @data[idx]
- @data[idx] += arg[:data][idx]
- }
- end
-
- # If true, displays a drop shadow for the chart
- attr_accessor :show_shadow
- # Sets the offset of the shadow from the pie chart
- attr_accessor :shadow_offset
- # If true, display the data labels on the chart
- attr_accessor :show_data_labels
- # If true, display the actual field values in the data labels
- attr_accessor :show_actual_values
- # If true, display the percentage value of each pie wedge in the data
- # labels
- attr_accessor :show_percent
- # If true, display the labels in the key
- attr_accessor :show_key_data_labels
- # If true, display the actual value of the field in the key
- attr_accessor :show_key_actual_values
- # If true, display the percentage value of the wedges in the key
- attr_accessor :show_key_percent
- # If true, "explode" the pie (put space between the wedges)
- attr_accessor :expanded
- # If true, expand the largest pie wedge
- attr_accessor :expand_greatest
- # The amount of space between expanded wedges
- attr_accessor :expand_gap
- # The font size of the data point labels
- attr_accessor :datapoint_font_size
-
-
- protected
-
- def add_defs defs
- gradient = defs.add_element( "filter", {
- "id"=>"dropshadow",
- "width" => "1.2",
- "height" => "1.2",
- } )
- gradient.add_element( "feGaussianBlur", {
- "stdDeviation" => "4",
- "result" => "blur"
- })
- end
-
- # We don't need the graph
- def draw_graph
- end
-
- def get_y_labels
- [""]
- end
-
- def get_x_labels
- [""]
- end
-
- def keys
- total = 0
- max_value = 0
- @data.each {|x| total += x }
- percent_scale = 100.0 / total
- count = -1
- a = @config[:fields].collect{ |x|
- count += 1
- v = @data[count]
- perc = show_key_percent ? " "+(v * percent_scale).round.to_s+"%" : ""
- x + " [" + v.to_s + "]" + perc
- }
- end
-
- RADIANS = Math::PI/180
-
- def draw_data
- @graph = @root.add_element( "g" )
- background = @graph.add_element("g")
- midground = @graph.add_element("g")
-
- diameter = @graph_height > @graph_width ? @graph_width : @graph_height
- diameter -= expand_gap if expanded or expand_greatest
- diameter -= datapoint_font_size if show_data_labels
- diameter -= 10 if show_shadow
- radius = diameter / 2.0
-
- xoff = (width - diameter) / 2
- yoff = (height - @border_bottom - diameter)
- yoff -= 10 if show_shadow
- @graph.attributes['transform'] = "translate( #{xoff} #{yoff} )"
-
- wedge_text_pad = 5
- wedge_text_pad = 20 if show_percent and show_data_labels
-
- total = 0
- max_value = 0
- @data.each {|x|
- max_value = max_value < x ? x : max_value
- total += x
- }
- percent_scale = 100.0 / total
-
- prev_percent = 0
- rad_mult = 3.6 * RADIANS
- @config[:fields].each_index { |count|
- value = @data[count]
- percent = percent_scale * value
-
- radians = prev_percent * rad_mult
- x_start = radius+(Math.sin(radians) * radius)
- y_start = radius-(Math.cos(radians) * radius)
- radians = (prev_percent+percent) * rad_mult
- x_end = radius+(Math.sin(radians) * radius)
- x_end -= 0.00001 if @data.length == 1
- y_end = radius-(Math.cos(radians) * radius)
- path = "M#{radius},#{radius} L#{x_start},#{y_start} "+
- "A#{radius},#{radius} "+
- "0, #{percent >= 50 ? '1' : '0'},1, "+
- "#{x_end} #{y_end} Z"
-
-
- wedge = @foreground.add_element( "path", {
- "d" => path,
- "class" => "fill#{count+1}"
- })
-
- translate = nil
- tx = 0
- ty = 0
- half_percent = prev_percent + percent / 2
- radians = half_percent * rad_mult
-
- if show_shadow
- shadow = background.add_element( "path", {
- "d" => path,
- "filter" => "url(#dropshadow)",
- "style" => "fill: #ccc; stroke: none;"
- })
- clear = midground.add_element( "path", {
- "d" => path,
- "style" => "fill: #fff; stroke: none;"
- })
- end
-
- if expanded or (expand_greatest && value == max_value)
- tx = (Math.sin(radians) * expand_gap)
- ty = -(Math.cos(radians) * expand_gap)
- translate = "translate( #{tx} #{ty} )"
- wedge.attributes["transform"] = translate
- clear.attributes["transform"] = translate if clear
- end
-
- if show_shadow
- shadow.attributes["transform"] =
- "translate( #{tx+shadow_offset} #{ty+shadow_offset} )"
- end
-
- if show_data_labels and value != 0
- label = ""
- label += @config[:fields][count] if show_key_data_labels
- label += " ["+value.to_s+"]" if show_actual_values
- label += " "+percent.round.to_s+"%" if show_percent
-
- msr = Math.sin(radians)
- mcr = Math.cos(radians)
- tx = radius + (msr * radius)
- ty = radius -(mcr * radius)
-
- if expanded or (expand_greatest && value == max_value)
- tx += (msr * expand_gap)
- ty -= (mcr * expand_gap)
- end
- @foreground.add_element( "text", {
- "x" => tx.to_s,
- "y" => ty.to_s,
- "class" => "dataPointLabel",
- "style" => "stroke: #fff; stroke-width: 2;"
- }).text = label.to_s
- @foreground.add_element( "text", {
- "x" => tx.to_s,
- "y" => ty.to_s,
- "class" => "dataPointLabel",
- }).text = label.to_s
- end
-
- prev_percent += percent
- }
- end
-
-
- def round val, to
- up = 10**to.to_f
- (val * up).to_i / up
- end
-
-
- def get_css
- return < 500,
- # :width => 300,
- # :key => true,
- # :scale_x_integers => true,
- # :scale_y_integerrs => true,
- # })
- #
- # graph.add_data({
- # :data => projection
- # :title => 'Projected',
- # })
- #
- # graph.add_data({
- # :data => actual,
- # :title => 'Actual',
- # })
- #
- # print graph.burn()
- #
- # = Description
- #
- # Produces a graph of scalar data.
- #
- # This object aims to allow you to easily create high quality
- # SVG[http://www.w3c.org/tr/svg] scalar plots. You can either use the
- # default style sheet or supply your own. Either way there are many options
- # which can be configured to give you control over how the graph is
- # generated - with or without a key, data elements at each point, title,
- # subtitle etc.
- #
- # = Examples
- #
- # http://www.germane-software/repositories/public/SVG/test/plot.rb
- #
- # = Notes
- #
- # The default stylesheet handles upto 10 data sets, if you
- # use more you must create your own stylesheet and add the
- # additional settings for the extra data sets. You will know
- # if you go over 10 data sets as they will have no style and
- # be in black.
- #
- # Unlike the other types of charts, data sets must contain x,y pairs:
- #
- # [ 1, 2 ] # A data set with 1 point: (1,2)
- # [ 1,2, 5,6] # A data set with 2 points: (1,2) and (5,6)
- #
- # = See also
- #
- # * SVG::Graph::Graph
- # * SVG::Graph::BarHorizontal
- # * SVG::Graph::Bar
- # * SVG::Graph::Line
- # * SVG::Graph::Pie
- # * SVG::Graph::TimeSeries
- #
- # == Author
- #
- # Sean E. Russell
- #
- # Copyright 2004 Sean E. Russell
- # This software is available under the Ruby license[LICENSE.txt]
- #
- class Plot < Graph
-
- # In addition to the defaults set by Graph::initialize, sets
- # [show_data_values] true
- # [show_data_points] true
- # [area_fill] false
- # [stacked] false
- def set_defaults
- init_with(
- :show_data_values => true,
- :show_data_points => true,
- :area_fill => false,
- :stacked => false
- )
- self.top_align = self.right_align = self.top_font = self.right_font = 1
- end
-
- # Determines the scaling for the X axis divisions.
- #
- # graph.scale_x_divisions = 2
- #
- # would cause the graph to attempt to generate labels stepped by 2; EG:
- # 0,2,4,6,8...
- attr_accessor :scale_x_divisions
- # Determines the scaling for the Y axis divisions.
- #
- # graph.scale_y_divisions = 0.5
- #
- # would cause the graph to attempt to generate labels stepped by 0.5; EG:
- # 0, 0.5, 1, 1.5, 2, ...
- attr_accessor :scale_y_divisions
- # Make the X axis labels integers
- attr_accessor :scale_x_integers
- # Make the Y axis labels integers
- attr_accessor :scale_y_integers
- # Fill the area under the line
- attr_accessor :area_fill
- # Show a small circle on the graph where the line
- # goes from one point to the next.
- attr_accessor :show_data_points
- # Set the minimum value of the X axis
- attr_accessor :min_x_value
- # Set the minimum value of the Y axis
- attr_accessor :min_y_value
-
-
- # Adds data to the plot. The data must be in X,Y pairs; EG
- # [ 1, 2 ] # A data set with 1 point: (1,2)
- # [ 1,2, 5,6] # A data set with 2 points: (1,2) and (5,6)
- def add_data data
- @data = [] unless @data
-
- raise "No data provided by #{conf.inspect}" unless data[:data] and
- data[:data].kind_of? Array
- raise "Data supplied must be x,y pairs! "+
- "The data provided contained an odd set of "+
- "data points" unless data[:data].length % 2 == 0
- return if data[:data].length == 0
-
- x = []
- y = []
- data[:data].each_index {|i|
- (i%2 == 0 ? x : y) << data[:data][i]
- }
- sort( x, y )
- data[:data] = [x,y]
- @data << data
- end
-
-
- protected
-
- def keys
- @data.collect{ |x| x[:title] }
- end
-
- def calculate_left_margin
- super
- label_left = get_x_labels[0].to_s.length / 2 * font_size * 0.6
- @border_left = label_left if label_left > @border_left
- end
-
- def calculate_right_margin
- super
- label_right = get_x_labels[-1].to_s.length / 2 * font_size * 0.6
- @border_right = label_right if label_right > @border_right
- end
-
-
- X = 0
- Y = 1
- def x_range
- max_value = @data.collect{|x| x[:data][X][-1] }.max
- min_value = @data.collect{|x| x[:data][X][0] }.min
- min_value = min_value "M#{x_start} #@graph_height #{lpath} V#@graph_height Z",
- "class" => "fill#{line}"
- })
- end
-
- @graph.add_element( "path", {
- "d" => "M#{x_start} #{y_start} #{lpath}",
- "class" => "line#{line}"
- })
-
- if show_data_points || show_data_values
- x_points.each_index { |idx|
- x = (x_points[idx] - x_min) * x_step
- y = @graph_height - (y_points[idx] - y_min) * y_step
- if show_data_points
- @graph.add_element( "circle", {
- "cx" => x.to_s,
- "cy" => y.to_s,
- "r" => "2.5",
- "class" => "dataPoint#{line}"
- })
- add_popup(x, y, format( x_points[idx], y_points[idx] )) if add_popups
- end
- make_datapoint_text( x, y-6, y_points[idx] ) if show_data_values
- }
- end
- line += 1
- end
- end
-
- def format x, y
- "(#{(x * 100).to_i / 100}, #{(y * 100).to_i / 100})"
- end
-
- def get_css
- return < 640,
- # :height => 480,
- # :graph_title => title,
- # :show_graph_title => true,
- # :no_css => true,
- # :scale_x_integers => true,
- # :scale_y_integers => true,
- # :min_x_value => 0,
- # :min_y_value => 0,
- # :show_data_labels => true,
- # :show_x_guidelines => true,
- # :show_x_title => true,
- # :x_title => "Time",
- # :stagger_x_labels => true,
- # :stagger_y_labels => true,
- # :x_label_format => "%m/%d/%y",
- # })
- #
- # graph.add_data({
- # :data => data1,
- # :title => 'Data',
- # })
- #
- # print graph.burn()
- #
- # = Description
- #
- # Produces a graph of temporal scalar data.
- #
- # = Examples
- #
- # http://www.germane-software/repositories/public/SVG/test/schedule.rb
- #
- # = Notes
- #
- # The default stylesheet handles upto 10 data sets, if you
- # use more you must create your own stylesheet and add the
- # additional settings for the extra data sets. You will know
- # if you go over 10 data sets as they will have no style and
- # be in black.
- #
- # Note that multiple data sets within the same chart can differ in
- # length, and that the data in the datasets needn't be in order;
- # they will be ordered by the plot along the X-axis.
- #
- # The dates must be parseable by ParseDate, but otherwise can be
- # any order of magnitude (seconds within the hour, or years)
- #
- # = See also
- #
- # * SVG::Graph::Graph
- # * SVG::Graph::BarHorizontal
- # * SVG::Graph::Bar
- # * SVG::Graph::Line
- # * SVG::Graph::Pie
- # * SVG::Graph::Plot
- # * SVG::Graph::TimeSeries
- #
- # == Author
- #
- # Sean E. Russell
- #
- # Copyright 2004 Sean E. Russell
- # This software is available under the Ruby license[LICENSE.txt]
- #
- class Schedule < Graph
- # In addition to the defaults set by Graph::initialize and
- # Plot::set_defaults, sets:
- # [x_label_format] '%Y-%m-%d %H:%M:%S'
- # [popup_format] '%Y-%m-%d %H:%M:%S'
- def set_defaults
- init_with(
- :x_label_format => '%Y-%m-%d %H:%M:%S',
- :popup_format => '%Y-%m-%d %H:%M:%S',
- :scale_x_divisions => false,
- :scale_x_integers => false,
- :bar_gap => true
- )
- end
-
- # The format string use do format the X axis labels.
- # See Time::strformat
- attr_accessor :x_label_format
- # Use this to set the spacing between dates on the axis. The value
- # must be of the form
- # "\d+ ?(days|weeks|months|years|hours|minutes|seconds)?"
- #
- # EG:
- #
- # graph.timescale_divisions = "2 weeks"
- #
- # will cause the chart to try to divide the X axis up into segments of
- # two week periods.
- attr_accessor :timescale_divisions
- # The formatting used for the popups. See x_label_format
- attr_accessor :popup_format
- attr_accessor :min_x_value
- attr_accessor :scale_x_divisions
- attr_accessor :scale_x_integers
- attr_accessor :bar_gap
-
- # Add data to the plot.
- #
- # # A data set with 1 point: Lunch from 12:30 to 14:00
- # d1 = [ "Lunch", "12:30", "14:00" ]
- # # A data set with 2 points: "Cats" runs from 5/11/03 to 7/15/04, and
- # # "Henry V" runs from 6/12/03 to 8/20/03
- # d2 = [ "Cats", "5/11/03", "7/15/04",
- # "Henry V", "6/12/03", "8/20/03" ]
- #
- # graph.add_data(
- # :data => d1,
- # :title => 'Meetings'
- # )
- # graph.add_data(
- # :data => d2,
- # :title => 'Plays'
- # )
- #
- # Note that the data must be in time,value pairs, and that the date format
- # may be any date that is parseable by ParseDate.
- # Also note that, in this example, we're mixing scales; the data from d1
- # will probably not be discernable if both data sets are plotted on the same
- # graph, since d1 is too granular.
- def add_data data
- @data = [] unless @data
-
- raise "No data provided by #{conf.inspect}" unless data[:data] and
- data[:data].kind_of? Array
- raise "Data supplied must be title,from,to tripples! "+
- "The data provided contained an odd set of "+
- "data points" unless data[:data].length % 3 == 0
- return if data[:data].length == 0
-
-
- y = []
- x_start = []
- x_end = []
- data[:data].each_index {|i|
- im3 = i%3
- if im3 == 0
- y << data[:data][i]
- else
- arr = ParseDate.parsedate( data[:data][i] )
- t = Time.local( *arr[0,6].compact )
- (im3 == 1 ? x_start : x_end) << t.to_i
- end
- }
- sort( x_start, x_end, y )
- @data = [x_start, x_end, y ]
- end
-
-
- protected
-
- def min_x_value=(value)
- arr = ParseDate.parsedate( value )
- @min_x_value = Time.local( *arr[0,6].compact ).to_i
- end
-
-
- def format x, y
- Time.at( x ).strftime( popup_format )
- end
-
- def get_x_labels
- rv = get_x_values.collect { |v| Time.at(v).strftime( x_label_format ) }
- end
-
- def y_label_offset( height )
- height / -2.0
- end
-
- def get_y_labels
- @data[2]
- end
-
- def draw_data
- fieldheight = field_height
- fieldwidth = field_width
-
- bargap = bar_gap ? (fieldheight < 10 ? fieldheight / 2 : 10) : 0
- subbar_height = fieldheight - bargap
-
- field_count = 1
- y_mod = (subbar_height / 2) + (font_size / 2)
- min,max,div = x_range
- scale = (@graph_width.to_f - font_size*2) / (max-min)
- @data[0].each_index { |i|
- x_start = @data[0][i]
- x_end = @data[1][i]
- y = @graph_height - (fieldheight * field_count)
- bar_width = (x_end-x_start) * scale
- bar_start = x_start * scale - (min * scale)
-
- @graph.add_element( "rect", {
- "x" => bar_start.to_s,
- "y" => y.to_s,
- "width" => bar_width.to_s,
- "height" => subbar_height.to_s,
- "class" => "fill#{field_count+1}"
- })
- field_count += 1
- }
- end
-
- def get_css
- return < 12
- arr[5] += (arr[4] / 12).to_i
- arr[4] = (arr[4] % 12)
- end
- cur = Time.local(*arr).to_i
- end
- when "years"
- cur = min
- while cur < max
- rv << cur
- arr = Time.at( cur ).to_a
- arr[5] += amount
- cur = Time.local(*arr).to_i
- end
- when "weeks"
- step = 7 * 24 * 60 * 60 * amount
- when "days"
- step = 24 * 60 * 60 * amount
- when "hours"
- step = 60 * 60 * amount
- when "minutes"
- step = 60 * amount
- when "seconds"
- step = amount
- end
- min.step( max, step ) {|v| rv << v} if step
-
- return rv
- end
- end
- min.step( max, scale_division ) {|v| rv << v}
- return rv
- end
- end
- end
-end
diff --git a/trustie2/lib/SVG/Graph/TimeSeries.rb b/trustie2/lib/SVG/Graph/TimeSeries.rb
deleted file mode 100644
index 3f45b291d..000000000
--- a/trustie2/lib/SVG/Graph/TimeSeries.rb
+++ /dev/null
@@ -1,238 +0,0 @@
-require 'SVG/Graph/Plot'
-
-module SVG
- module Graph
- # === For creating SVG plots of scalar temporal data
- #
- # = Synopsis
- #
- # require 'SVG/Graph/TimeSeriess'
- #
- # # Data sets are x,y pairs
- # data1 = ["6/17/72", 11, "1/11/72", 7, "4/13/04 17:31", 11,
- # "9/11/01", 9, "9/1/85", 2, "9/1/88", 1, "1/15/95", 13]
- # data2 = ["8/1/73", 18, "3/1/77", 15, "10/1/98", 4,
- # "5/1/02", 14, "3/1/95", 6, "8/1/91", 12, "12/1/87", 6,
- # "5/1/84", 17, "10/1/80", 12]
- #
- # graph = SVG::Graph::TimeSeries.new( {
- # :width => 640,
- # :height => 480,
- # :graph_title => title,
- # :show_graph_title => true,
- # :no_css => true,
- # :key => true,
- # :scale_x_integers => true,
- # :scale_y_integers => true,
- # :min_x_value => 0,
- # :min_y_value => 0,
- # :show_data_labels => true,
- # :show_x_guidelines => true,
- # :show_x_title => true,
- # :x_title => "Time",
- # :show_y_title => true,
- # :y_title => "Ice Cream Cones",
- # :y_title_text_direction => :bt,
- # :stagger_x_labels => true,
- # :x_label_format => "%m/%d/%y",
- # })
- #
- # graph.add_data({
- # :data => projection
- # :title => 'Projected',
- # })
- #
- # graph.add_data({
- # :data => actual,
- # :title => 'Actual',
- # })
- #
- # print graph.burn()
- #
- # = Description
- #
- # Produces a graph of temporal scalar data.
- #
- # = Examples
- #
- # http://www.germane-software/repositories/public/SVG/test/timeseries.rb
- #
- # = Notes
- #
- # The default stylesheet handles upto 10 data sets, if you
- # use more you must create your own stylesheet and add the
- # additional settings for the extra data sets. You will know
- # if you go over 10 data sets as they will have no style and
- # be in black.
- #
- # Unlike the other types of charts, data sets must contain x,y pairs:
- #
- # [ "12:30", 2 ] # A data set with 1 point: ("12:30",2)
- # [ "01:00",2, "14:20",6] # A data set with 2 points: ("01:00",2) and
- # # ("14:20",6)
- #
- # Note that multiple data sets within the same chart can differ in length,
- # and that the data in the datasets needn't be in order; they will be ordered
- # by the plot along the X-axis.
- #
- # The dates must be parseable by ParseDate, but otherwise can be
- # any order of magnitude (seconds within the hour, or years)
- #
- # = See also
- #
- # * SVG::Graph::Graph
- # * SVG::Graph::BarHorizontal
- # * SVG::Graph::Bar
- # * SVG::Graph::Line
- # * SVG::Graph::Pie
- # * SVG::Graph::Plot
- #
- # == Author
- #
- # Sean E. Russell
- #
- # Copyright 2004 Sean E. Russell
- # This software is available under the Ruby license[LICENSE.txt]
- #
- class TimeSeries < Plot
- # In addition to the defaults set by Graph::initialize and
- # Plot::set_defaults, sets:
- # [x_label_format] '%Y-%m-%d %H:%M:%S'
- # [popup_format] '%Y-%m-%d %H:%M:%S'
- def set_defaults
- super
- init_with(
- #:max_time_span => '',
- :x_label_format => '%Y-%m-%d %H:%M:%S',
- :popup_format => '%Y-%m-%d %H:%M:%S'
- )
- end
-
- # The format string use do format the X axis labels.
- # See Time::strformat
- attr_accessor :x_label_format
- # Use this to set the spacing between dates on the axis. The value
- # must be of the form
- # "\d+ ?(days|weeks|months|years|hours|minutes|seconds)?"
- #
- # EG:
- #
- # graph.timescale_divisions = "2 weeks"
- #
- # will cause the chart to try to divide the X axis up into segments of
- # two week periods.
- attr_accessor :timescale_divisions
- # The formatting used for the popups. See x_label_format
- attr_accessor :popup_format
-
- # Add data to the plot.
- #
- # d1 = [ "12:30", 2 ] # A data set with 1 point: ("12:30",2)
- # d2 = [ "01:00",2, "14:20",6] # A data set with 2 points: ("01:00",2) and
- # # ("14:20",6)
- # graph.add_data(
- # :data => d1,
- # :title => 'One'
- # )
- # graph.add_data(
- # :data => d2,
- # :title => 'Two'
- # )
- #
- # Note that the data must be in time,value pairs, and that the date format
- # may be any date that is parseable by ParseDate.
- def add_data data
- @data = [] unless @data
-
- raise "No data provided by #{@data.inspect}" unless data[:data] and
- data[:data].kind_of? Array
- raise "Data supplied must be x,y pairs! "+
- "The data provided contained an odd set of "+
- "data points" unless data[:data].length % 2 == 0
- return if data[:data].length == 0
-
-
- x = []
- y = []
- data[:data].each_index {|i|
- if i%2 == 0
- t = DateTime.parse( data[:data][i] ).to_time
- x << t.to_i
- else
- y << data[:data][i]
- end
- }
- sort( x, y )
- data[:data] = [x,y]
- @data << data
- end
-
-
- protected
-
- def min_x_value=(value)
- @min_x_value = DateTime.parse( value ).to_time
- end
-
-
- def format x, y
- Time.at( x ).strftime( popup_format )
- end
-
- def get_x_labels
- get_x_values.collect { |v| Time.at(v).strftime( x_label_format ) }
- end
-
- private
- def get_x_values
- rv = []
- min, max, scale_division = x_range
- if timescale_divisions
- timescale_divisions =~ /(\d+) ?(day|week|month|year|hour|minute|second)?/
- division_units = $2 ? $2 : "day"
- amount = $1.to_i
- if amount
- step = nil
- case division_units
- when "month"
- cur = min
- while cur < max
- rv << cur
- arr = Time.at( cur ).to_a
- arr[4] += amount
- if arr[4] > 12
- arr[5] += (arr[4] / 12).to_i
- arr[4] = (arr[4] % 12)
- end
- cur = Time.local(*arr).to_i
- end
- when "year"
- cur = min
- while cur < max
- rv << cur
- arr = Time.at( cur ).to_a
- arr[5] += amount
- cur = Time.local(*arr).to_i
- end
- when "week"
- step = 7 * 24 * 60 * 60 * amount
- when "day"
- step = 24 * 60 * 60 * amount
- when "hour"
- step = 60 * 60 * amount
- when "minute"
- step = 60 * amount
- when "second"
- step = amount
- end
- min.step( max, step ) {|v| rv << v} if step
-
- return rv
- end
- end
- min.step( max, scale_division ) {|v| rv << v}
- return rv
- end
- end
- end
-end
diff --git a/trustie2/lib/SVG/LICENSE.txt b/trustie2/lib/SVG/LICENSE.txt
deleted file mode 100644
index 2b945d276..000000000
--- a/trustie2/lib/SVG/LICENSE.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-SVG::Graph is copyrighted free software by Sean Russell .
-You can redistribute it and/or modify it under either the terms of the GPL
-(see GPL.txt file), or the conditions below:
-
- 1. You may make and give away verbatim copies of the source form of the
- software without restriction, provided that you duplicate all of the
- original copyright notices and associated disclaimers.
-
- 2. You may modify your copy of the software in any way, provided that
- you do at least ONE of the following:
-
- a) place your modifications in the Public Domain or otherwise
- make them Freely Available, such as by posting said
- modifications to Usenet or an equivalent medium, or by allowing
- the author to include your modifications in the software.
-
- b) use the modified software only within your corporation or
- organization.
-
- c) rename any non-standard executables so the names do not conflict
- with standard executables, which must also be provided.
-
- d) make other distribution arrangements with the author.
-
- 3. You may distribute the software in object code or executable
- form, provided that you do at least ONE of the following:
-
- a) distribute the executables and library files of the software,
- together with instructions (in the manual page or equivalent)
- on where to get the original distribution.
-
- b) accompany the distribution with the machine-readable source of
- the software.
-
- c) give non-standard executables non-standard names, with
- instructions on where to get the original software distribution.
-
- d) make other distribution arrangements with the author.
-
- 4. You may modify and include the part of the software into any other
- software (possibly commercial). But some files in the distribution
- are not written by the author, so that they are not under this terms.
-
- All files of this sort are located under the contrib/ directory.
- See each file for the copying condition.
-
- 5. The scripts and library files supplied as input to or produced as
- output from the software do not automatically fall under the
- copyright of the software, but belong to whomever generated them,
- and may be sold commercially, and may be aggregated with this
- software.
-
- 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE.
-
diff --git a/trustie2/lib/diff.rb b/trustie2/lib/diff.rb
deleted file mode 100644
index 9e1653f14..000000000
--- a/trustie2/lib/diff.rb
+++ /dev/null
@@ -1,282 +0,0 @@
-module RedmineDiff
- class Diff
-
- VERSION = 0.3
-
- def Diff.lcs(a, b)
- astart = 0
- bstart = 0
- afinish = a.length-1
- bfinish = b.length-1
- mvector = []
-
- # First we prune off any common elements at the beginning
- while (astart <= afinish && bstart <= afinish && a[astart] == b[bstart])
- mvector[astart] = bstart
- astart += 1
- bstart += 1
- end
-
- # now the end
- while (astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish])
- mvector[afinish] = bfinish
- afinish -= 1
- bfinish -= 1
- end
-
- bmatches = b.reverse_hash(bstart..bfinish)
- thresh = []
- links = []
-
- (astart..afinish).each { |aindex|
- aelem = a[aindex]
- next unless bmatches.has_key? aelem
- k = nil
- bmatches[aelem].reverse.each { |bindex|
- if k && (thresh[k] > bindex) && (thresh[k-1] < bindex)
- thresh[k] = bindex
- else
- k = thresh.replacenextlarger(bindex, k)
- end
- links[k] = [ (k==0) ? nil : links[k-1], aindex, bindex ] if k
- }
- }
-
- if !thresh.empty?
- link = links[thresh.length-1]
- while link
- mvector[link[1]] = link[2]
- link = link[0]
- end
- end
-
- return mvector
- end
-
- def makediff(a, b)
- mvector = Diff.lcs(a, b)
- ai = bi = 0
- while ai < mvector.length
- bline = mvector[ai]
- if bline
- while bi < bline
- discardb(bi, b[bi])
- bi += 1
- end
- match(ai, bi)
- bi += 1
- else
- discarda(ai, a[ai])
- end
- ai += 1
- end
- while ai < a.length
- discarda(ai, a[ai])
- ai += 1
- end
- while bi < b.length
- discardb(bi, b[bi])
- bi += 1
- end
- match(ai, bi)
- 1
- end
-
- def compactdiffs
- diffs = []
- @diffs.each { |df|
- i = 0
- curdiff = []
- while i < df.length
- whot = df[i][0]
- s = @isstring ? df[i][2].chr : [df[i][2]]
- p = df[i][1]
- last = df[i][1]
- i += 1
- while df[i] && df[i][0] == whot && df[i][1] == last+1
- s << df[i][2]
- last = df[i][1]
- i += 1
- end
- curdiff.push [whot, p, s]
- end
- diffs.push curdiff
- }
- return diffs
- end
-
- attr_reader :diffs, :difftype
-
- def initialize(diffs_or_a, b = nil, isstring = nil)
- if b.nil?
- @diffs = diffs_or_a
- @isstring = isstring
- else
- @diffs = []
- @curdiffs = []
- makediff(diffs_or_a, b)
- @difftype = diffs_or_a.class
- end
- end
-
- def match(ai, bi)
- @diffs.push @curdiffs unless @curdiffs.empty?
- @curdiffs = []
- end
-
- def discarda(i, elem)
- @curdiffs.push ['-', i, elem]
- end
-
- def discardb(i, elem)
- @curdiffs.push ['+', i, elem]
- end
-
- def compact
- return Diff.new(compactdiffs)
- end
-
- def compact!
- @diffs = compactdiffs
- end
-
- def inspect
- @diffs.inspect
- end
-
- end
-end
-
-module Diffable
- def diff(b)
- RedmineDiff::Diff.new(self, b)
- end
-
- # Create a hash that maps elements of the array to arrays of indices
- # where the elements are found.
-
- def reverse_hash(range = (0...self.length))
- revmap = {}
- range.each { |i|
- elem = self[i]
- if revmap.has_key? elem
- revmap[elem].push i
- else
- revmap[elem] = [i]
- end
- }
- return revmap
- end
-
- def replacenextlarger(value, high = nil)
- high ||= self.length
- if self.empty? || value > self[-1]
- push value
- return high
- end
- # binary search for replacement point
- low = 0
- while low < high
- index = (high+low)/2
- found = self[index]
- return nil if value == found
- if value > found
- low = index + 1
- else
- high = index
- end
- end
-
- self[low] = value
- # $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_high-low} off )\n"
- # $stderr.puts self.inspect
- #gets
- #p length - low
- return low
- end
-
- def patch(diff)
- newary = nil
- if diff.difftype == String
- newary = diff.difftype.new('')
- else
- newary = diff.difftype.new
- end
- ai = 0
- bi = 0
- diff.diffs.each { |d|
- d.each { |mod|
- case mod[0]
- when '-'
- while ai < mod[1]
- newary << self[ai]
- ai += 1
- bi += 1
- end
- ai += 1
- when '+'
- while bi < mod[1]
- newary << self[ai]
- ai += 1
- bi += 1
- end
- newary << mod[2]
- bi += 1
- else
- raise "Unknown diff action"
- end
- }
- }
- while ai < self.length
- newary << self[ai]
- ai += 1
- bi += 1
- end
- return newary
- end
-end
-
-class Array
- include Diffable
-end
-
-class String
- include Diffable
-end
-
-=begin
- = Diff
- (({diff.rb})) - computes the differences between two arrays or
- strings. Copyright (C) 2001 Lars Christensen
-
- == Synopsis
-
- diff = Diff.new(a, b)
- b = a.patch(diff)
-
- == Class Diff
- === Class Methods
- --- Diff.new(a, b)
- --- a.diff(b)
- Creates a Diff object which represent the differences between
- ((|a|)) and ((|b|)). ((|a|)) and ((|b|)) can be either be arrays
- of any objects, strings, or object of any class that include
- module ((|Diffable|))
-
- == Module Diffable
- The module ((|Diffable|)) is intended to be included in any class for
- which differences are to be computed. Diffable is included into String
- and Array when (({diff.rb})) is (({require}))'d.
-
- Classes including Diffable should implement (({[]})) to get element at
- integer indices, (({<<})) to append elements to the object and
- (({ClassName#new})) should accept 0 arguments to create a new empty
- object.
-
- === Instance Methods
- --- Diffable#patch(diff)
- Applies the differences from ((|diff|)) to the object ((|obj|))
- and return the result. ((|obj|)) is not changed. ((|obj|)) and
- can be either an array or a string, but must match the object
- from which the ((|diff|)) was created.
-=end
diff --git a/trustie2/lib/generators/redmine_plugin/USAGE b/trustie2/lib/generators/redmine_plugin/USAGE
deleted file mode 100644
index 793f2fc5e..000000000
--- a/trustie2/lib/generators/redmine_plugin/USAGE
+++ /dev/null
@@ -1,26 +0,0 @@
-Description:
- The plugin generator creates stubs for a new Redmine plugin.
-
-Example:
- ./script/rails generate redmine_plugin meetings
- create plugins/meetings/app
- create plugins/meetings/app/controllers
- create plugins/meetings/app/helpers
- create plugins/meetings/app/models
- create plugins/meetings/app/views
- create plugins/meetings/db/migrate
- create plugins/meetings/lib/tasks
- create plugins/meetings/assets/images
- create plugins/meetings/assets/javascripts
- create plugins/meetings/assets/stylesheets
- create plugins/meetings/config/locales
- create plugins/meetings/test
- create plugins/meetings/test/fixtures
- create plugins/meetings/test/unit
- create plugins/meetings/test/functional
- create plugins/meetings/test/integration
- create plugins/meetings/README.rdoc
- create plugins/meetings/init.rb
- create plugins/meetings/config/routes.rb
- create plugins/meetings/config/locales/en.yml
- create plugins/meetings/test/test_helper.rb
diff --git a/trustie2/lib/generators/redmine_plugin/redmine_plugin_generator.rb b/trustie2/lib/generators/redmine_plugin/redmine_plugin_generator.rb
deleted file mode 100644
index 562366342..000000000
--- a/trustie2/lib/generators/redmine_plugin/redmine_plugin_generator.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-class RedminePluginGenerator < Rails::Generators::NamedBase
- source_root File.expand_path("../templates", __FILE__)
-
- attr_reader :plugin_path, :plugin_name, :plugin_pretty_name
-
- def initialize(*args)
- super
- @plugin_name = file_name.underscore
- @plugin_pretty_name = plugin_name.titleize
- @plugin_path = "plugins/#{plugin_name}"
- end
-
- def copy_templates
- empty_directory "#{plugin_path}/app"
- empty_directory "#{plugin_path}/app/controllers"
- empty_directory "#{plugin_path}/app/helpers"
- empty_directory "#{plugin_path}/app/models"
- empty_directory "#{plugin_path}/app/views"
- empty_directory "#{plugin_path}/db/migrate"
- empty_directory "#{plugin_path}/lib/tasks"
- empty_directory "#{plugin_path}/assets/images"
- empty_directory "#{plugin_path}/assets/javascripts"
- empty_directory "#{plugin_path}/assets/stylesheets"
- empty_directory "#{plugin_path}/config/locales"
- empty_directory "#{plugin_path}/test"
- empty_directory "#{plugin_path}/test/fixtures"
- empty_directory "#{plugin_path}/test/unit"
- empty_directory "#{plugin_path}/test/functional"
- empty_directory "#{plugin_path}/test/integration"
-
- template 'README.rdoc', "#{plugin_path}/README.rdoc"
- template 'init.rb.erb', "#{plugin_path}/init.rb"
- template 'routes.rb', "#{plugin_path}/config/routes.rb"
- template 'en_rails_i18n.yml', "#{plugin_path}/config/locales/en.yml"
- template 'test_helper.rb.erb', "#{plugin_path}/test/test_helper.rb"
- end
-end
diff --git a/trustie2/lib/generators/redmine_plugin/templates/README.rdoc b/trustie2/lib/generators/redmine_plugin/templates/README.rdoc
deleted file mode 100644
index 7a31a890e..000000000
--- a/trustie2/lib/generators/redmine_plugin/templates/README.rdoc
+++ /dev/null
@@ -1,3 +0,0 @@
-= <%= file_name %>
-
-Description goes here
diff --git a/trustie2/lib/generators/redmine_plugin/templates/en_rails_i18n.yml b/trustie2/lib/generators/redmine_plugin/templates/en_rails_i18n.yml
deleted file mode 100644
index 642b07f82..000000000
--- a/trustie2/lib/generators/redmine_plugin/templates/en_rails_i18n.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-# English strings go here for Rails i18n
-en:
- # my_label: "My label"
diff --git a/trustie2/lib/generators/redmine_plugin/templates/init.rb.erb b/trustie2/lib/generators/redmine_plugin/templates/init.rb.erb
deleted file mode 100644
index 763ba7d22..000000000
--- a/trustie2/lib/generators/redmine_plugin/templates/init.rb.erb
+++ /dev/null
@@ -1,8 +0,0 @@
-Redmine::Plugin.register :<%= plugin_name %> do
- name '<%= plugin_pretty_name %> plugin'
- author 'Author name'
- description 'This is a plugin for Redmine'
- version '0.0.1'
- url 'http://example.com/path/to/plugin'
- author_url 'http://example.com/about'
-end
diff --git a/trustie2/lib/generators/redmine_plugin/templates/routes.rb b/trustie2/lib/generators/redmine_plugin/templates/routes.rb
deleted file mode 100644
index 1803173d0..000000000
--- a/trustie2/lib/generators/redmine_plugin/templates/routes.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-# Plugin's routes
-# See: http://guides.rubyonrails.org/routing.html
diff --git a/trustie2/lib/generators/redmine_plugin/templates/test_helper.rb.erb b/trustie2/lib/generators/redmine_plugin/templates/test_helper.rb.erb
deleted file mode 100644
index 54685d33c..000000000
--- a/trustie2/lib/generators/redmine_plugin/templates/test_helper.rb.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-# Load the Redmine helper
-require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper')
diff --git a/trustie2/lib/generators/redmine_plugin_controller/USAGE b/trustie2/lib/generators/redmine_plugin_controller/USAGE
deleted file mode 100644
index adc3f82b3..000000000
--- a/trustie2/lib/generators/redmine_plugin_controller/USAGE
+++ /dev/null
@@ -1,5 +0,0 @@
-Description:
- Generates a plugin controller.
-
-Example:
- ./script/rails generate redmine_plugin_controller meetings pools index show vote
diff --git a/trustie2/lib/generators/redmine_plugin_controller/redmine_plugin_controller_generator.rb b/trustie2/lib/generators/redmine_plugin_controller/redmine_plugin_controller_generator.rb
deleted file mode 100644
index 8351ce681..000000000
--- a/trustie2/lib/generators/redmine_plugin_controller/redmine_plugin_controller_generator.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-class RedminePluginControllerGenerator < Rails::Generators::NamedBase
- source_root File.expand_path("../templates", __FILE__)
- argument :controller, :type => :string
- argument :actions, :type => :array, :default => [], :banner => "ACTION ACTION ..."
-
- attr_reader :plugin_path, :plugin_name, :plugin_pretty_name
-
- def initialize(*args)
- super
- @plugin_name = file_name.underscore
- @plugin_pretty_name = plugin_name.titleize
- @plugin_path = "plugins/#{plugin_name}"
- @controller_class = controller.camelize
- end
-
- def copy_templates
- template 'controller.rb.erb', "#{plugin_path}/app/controllers/#{controller}_controller.rb"
- template 'helper.rb.erb', "#{plugin_path}/app/helpers/#{controller}_helper.rb"
- template 'functional_test.rb.erb', "#{plugin_path}/test/functional/#{controller}_controller_test.rb"
- # View template for each action.
- actions.each do |action|
- path = "#{plugin_path}/app/views/#{controller}/#{action}.html.erb"
- @action_name = action
- template 'view.html.erb', path
- end
- end
-end
diff --git a/trustie2/lib/generators/redmine_plugin_controller/templates/controller.rb.erb b/trustie2/lib/generators/redmine_plugin_controller/templates/controller.rb.erb
deleted file mode 100644
index dddbf7017..000000000
--- a/trustie2/lib/generators/redmine_plugin_controller/templates/controller.rb.erb
+++ /dev/null
@@ -1,9 +0,0 @@
-class <%= @controller_class %>Controller < ApplicationController
- unloadable
-
-<% actions.each do |action| -%>
-
- def <%= action %>
- end
-<% end -%>
-end
diff --git a/trustie2/lib/generators/redmine_plugin_controller/templates/functional_test.rb.erb b/trustie2/lib/generators/redmine_plugin_controller/templates/functional_test.rb.erb
deleted file mode 100644
index 0499b6970..000000000
--- a/trustie2/lib/generators/redmine_plugin_controller/templates/functional_test.rb.erb
+++ /dev/null
@@ -1,8 +0,0 @@
-require File.expand_path('../../test_helper', __FILE__)
-
-class <%= @controller_class %>ControllerTest < ActionController::TestCase
- # Replace this with your real tests.
- def test_truth
- assert true
- end
-end
diff --git a/trustie2/lib/generators/redmine_plugin_controller/templates/helper.rb.erb b/trustie2/lib/generators/redmine_plugin_controller/templates/helper.rb.erb
deleted file mode 100644
index 059e12f3b..000000000
--- a/trustie2/lib/generators/redmine_plugin_controller/templates/helper.rb.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-module <%= @controller_class %>Helper
-end
diff --git a/trustie2/lib/generators/redmine_plugin_controller/templates/view.html.erb b/trustie2/lib/generators/redmine_plugin_controller/templates/view.html.erb
deleted file mode 100644
index 21d5b645a..000000000
--- a/trustie2/lib/generators/redmine_plugin_controller/templates/view.html.erb
+++ /dev/null
@@ -1 +0,0 @@
-<%= @controller_class %>Controller#<%= @action_name %>
diff --git a/trustie2/lib/generators/redmine_plugin_model/USAGE b/trustie2/lib/generators/redmine_plugin_model/USAGE
deleted file mode 100644
index 7b5d79857..000000000
--- a/trustie2/lib/generators/redmine_plugin_model/USAGE
+++ /dev/null
@@ -1,5 +0,0 @@
-Description:
- Generates a plugin model.
-
-Examples:
- ./script/rails generate redmine_plugin_model meetings pool
diff --git a/trustie2/lib/generators/redmine_plugin_model/redmine_plugin_model_generator.rb b/trustie2/lib/generators/redmine_plugin_model/redmine_plugin_model_generator.rb
deleted file mode 100644
index 2e5f03108..000000000
--- a/trustie2/lib/generators/redmine_plugin_model/redmine_plugin_model_generator.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-class RedminePluginModelGenerator < Rails::Generators::NamedBase
-
- source_root File.expand_path("../templates", __FILE__)
- argument :model, :type => :string
- argument :attributes, :type => :array, :default => [], :banner => "field[:type][:index] field[:type][:index]"
- class_option :migration, :type => :boolean
- class_option :timestamps, :type => :boolean
- class_option :parent, :type => :string, :desc => "The parent class for the generated model"
- class_option :indexes, :type => :boolean, :default => true, :desc => "Add indexes for references and belongs_to columns"
-
- attr_reader :plugin_path, :plugin_name, :plugin_pretty_name
-
- def initialize(*args)
- super
- @plugin_name = file_name.underscore
- @plugin_pretty_name = plugin_name.titleize
- @plugin_path = "plugins/#{plugin_name}"
- @model_class = model.camelize
- @table_name = @model_class.tableize
- @migration_filename = "create_#{@table_name}"
- @migration_class_name = @migration_filename.camelize
- end
-
- def copy_templates
- template 'model.rb.erb', "#{plugin_path}/app/models/#{model.underscore}.rb"
- template 'unit_test.rb.erb', "#{plugin_path}/test/unit/#{model.underscore}_test.rb"
-
- migration_filename = "%03i_#{@migration_filename}.rb" % (migration_number + 1)
- template "migration.rb", "#{plugin_path}/db/migrate/#{migration_filename}"
- end
-
- def attributes_with_index
- attributes.select { |a| a.has_index? || (a.reference? && options[:indexes]) }
- end
-
- def migration_number
- current = Dir.glob("#{plugin_path}/db/migrate/*.rb").map do |file|
- File.basename(file).split("_").first.to_i
- end.max.to_i
- end
-end
diff --git a/trustie2/lib/generators/redmine_plugin_model/templates/migration.rb b/trustie2/lib/generators/redmine_plugin_model/templates/migration.rb
deleted file mode 100644
index f5026aebf..000000000
--- a/trustie2/lib/generators/redmine_plugin_model/templates/migration.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class <%= @migration_class_name %> < ActiveRecord::Migration
- def change
- create_table :<%= @table_name %> do |t|
-<% attributes.each do |attribute| -%>
- t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
-<% end -%>
-<% if options[:timestamps] %>
- t.timestamps
-<% end -%>
- end
-<% attributes_with_index.each do |attribute| -%>
- add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
-<% end -%>
- end
-end
diff --git a/trustie2/lib/generators/redmine_plugin_model/templates/model.rb.erb b/trustie2/lib/generators/redmine_plugin_model/templates/model.rb.erb
deleted file mode 100644
index 71284e96d..000000000
--- a/trustie2/lib/generators/redmine_plugin_model/templates/model.rb.erb
+++ /dev/null
@@ -1,3 +0,0 @@
-class <%= @model_class %> < ActiveRecord::Base
- unloadable
-end
diff --git a/trustie2/lib/generators/redmine_plugin_model/templates/unit_test.rb.erb b/trustie2/lib/generators/redmine_plugin_model/templates/unit_test.rb.erb
deleted file mode 100644
index ad15149fa..000000000
--- a/trustie2/lib/generators/redmine_plugin_model/templates/unit_test.rb.erb
+++ /dev/null
@@ -1,9 +0,0 @@
-require File.expand_path('../../test_helper', __FILE__)
-
-class <%= @model_class %>Test < ActiveSupport::TestCase
-
- # Replace this with your real tests.
- def test_truth
- assert true
- end
-end
diff --git a/trustie2/lib/git/backend/grack_auth.rb b/trustie2/lib/git/backend/grack_auth.rb
deleted file mode 100644
index e7217c7c7..000000000
--- a/trustie2/lib/git/backend/grack_auth.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-require_relative 'shell_env'
-require_relative 'grack_ldap'
-require_relative 'grack_helpers'
-
-module Grack
- class Auth < Rack::Auth::Basic
- include LDAP
- include Helpers
-
- attr_accessor :user, :project, :ref, :env
-
- def call(env)
- @env = env
- @request = Rack::Request.new(env)
- @auth = Request.new(env)
-
- # Need this patch due to the rails mount
- @env['PATH_INFO'] = @request.path
- @env['SCRIPT_NAME'] = ""
-
- auth!
- end
-
- private
-
- def auth!
- return render_not_found unless project
-
- if @auth.provided?
- return bad_request unless @auth.basic?
-
- # Authentication with username and password
- login, password = @auth.credentials
-
- @user = authenticate_user(login, password)
-
- if @user
- Gitlab::ShellEnv.set_env(@user)
- @env['REMOTE_USER'] = @auth.username
- else
- return unauthorized
- end
-
- else
- return unauthorized unless project.public
- end
-
- if authorized_git_request?
- @app.call(env)
- else
- unauthorized
- end
- end
-
- def authorized_git_request?
- # Git upload and receive
- if @request.get?
- authorize_request(@request.params['service'])
- elsif @request.post?
- authorize_request(File.basename(@request.path))
- else
- false
- end
- end
-
- def authenticate_user(login, password)
- user = User.find_by_email(login) || User.find_by_username(login)
-
- # If the provided login was not a known email or username
- # then user is nil
- if user.nil? || user.ldap_user?
- # Second chance - try LDAP authentication
- return nil unless ldap_conf.enabled
-
- auth = Gitlab::Auth.new
- auth.ldap_auth(login, password)
- else
- return user if user.valid_password?(password)
- end
- end
-
- def authorize_request(service)
- case service
- when 'git-upload-pack'
- project.public || can?(user, :download_code, project)
- when'git-receive-pack'
- action = if project.protected_branch?(ref)
- :push_code_to_protected_branches
- else
- :push_code
- end
-
- can?(user, action, project)
- else
- false
- end
- end
-
- def project
- @project ||= project_by_path(@request.path_info)
- end
-
- def ref
- @ref ||= parse_ref
- end
-
- def parse_ref
- input = if @env["HTTP_CONTENT_ENCODING"] =~ /gzip/
- Zlib::GzipReader.new(@request.body).read
- else
- @request.body.read
- end
-
- # Need to reset seek point
- @request.body.rewind
- /refs\/heads\/([\w\.-]+)/n.match(input.force_encoding('ascii-8bit')).to_a.last
- end
- end
-end
diff --git a/trustie2/lib/git/backend/grack_helpers.rb b/trustie2/lib/git/backend/grack_helpers.rb
deleted file mode 100644
index 85c79e118..000000000
--- a/trustie2/lib/git/backend/grack_helpers.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-module Grack
- module Helpers
- def project_by_path(path)
- if m = /^\/([\w\.\/-]+)\.git/.match(path).to_a
- path_with_namespace = m.last
- path_with_namespace.gsub!(/\.wiki$/, '')
-
- Project.find_with_namespace(path_with_namespace)
- end
- end
-
- def render_not_found
- [404, {"Content-Type" => "text/plain"}, ["Not Found"]]
- end
-
- def can?(object, action, title)
- abilities.allowed?(object, action, title)
- end
-
- def abilities
- @abilities ||= begin
- abilities = Six.new
- abilities << Ability
- abilities
- end
- end
- end
-end
diff --git a/trustie2/lib/git/backend/grack_ldap.rb b/trustie2/lib/git/backend/grack_ldap.rb
deleted file mode 100644
index 45e98fbac..000000000
--- a/trustie2/lib/git/backend/grack_ldap.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require 'omniauth-ldap'
-
-module Grack
- module LDAP
- def ldap_auth(login, password)
- # Check user against LDAP backend if user is not authenticated
- # Only check with valid login and password to prevent anonymous bind results
- return nil unless ldap_conf.enabled && !login.blank? && !password.blank?
-
- ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
- ldap_user = ldap.bind_as(
- filter: Net::LDAP::Filter.eq(ldap.uid, login),
- size: 1,
- password: password
- )
-
- User.find_by_extern_uid_and_provider(ldap_user.dn, 'ldap') if ldap_user
- end
-
- def ldap_conf
- @ldap_conf ||= Gitlab.config.ldap
- end
- end
-end
diff --git a/trustie2/lib/git/backend/shell.rb b/trustie2/lib/git/backend/shell.rb
deleted file mode 100644
index 991648f3f..000000000
--- a/trustie2/lib/git/backend/shell.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-module Gitlab
- class Shell
- class AccessDenied < StandardError; end
-
- # Init new repository
- #
- # name - project path with namespace
- #
- # Ex.
- # add_repository("gitlab/gitlab-ci")
- #
- def add_repository(name)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "add-project", "#{name}.git"
- end
-
- # Import repository
- #
- # name - project path with namespace
- #
- # Ex.
- # import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git")
- #
- def import_repository(name, url)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "import-project", "#{name}.git", url
- end
-
- # Move repository
- #
- # path - project path with namespace
- # new_path - new project path with namespace
- #
- # Ex.
- # mv_repository("gitlab/gitlab-ci", "randx/gitlab-ci-new.git")
- #
- def mv_repository(path, new_path)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "mv-project", "#{path}.git", "#{new_path}.git"
- end
-
- # Fork repository to new namespace
- #
- # path - project path with namespace
- # fork_namespace - namespace for forked project
- #
- # Ex.
- # fork_repository("gitlab/gitlab-ci", "randx")
- #
- def fork_repository(path, fork_namespace)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "fork-project", "#{path}.git", fork_namespace
- end
-
- # Remove repository from file system
- #
- # name - project path with namespace
- #
- # Ex.
- # remove_repository("gitlab/gitlab-ci")
- #
- def remove_repository(name)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-projects", "rm-project", "#{name}.git"
- end
-
- # Add new key to gitlab-shell
- #
- # Ex.
- # add_key("key-42", "sha-rsa ...")
- #
- def add_key(key_id, key_content)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys", "add-key", key_id, key_content
- end
-
- # Remove ssh key from gitlab shell
- #
- # Ex.
- # remove_key("key-342", "sha-rsa ...")
- #
- def remove_key(key_id, key_content)
- system "#{gitlab_shell_user_home}/gitlab-shell/bin/gitlab-keys", "rm-key", key_id, key_content
- end
-
- # Add empty directory for storing repositories
- #
- # Ex.
- # add_namespace("gitlab")
- #
- def add_namespace(name)
- FileUtils.mkdir(full_path(name), mode: 0770) unless exists?(name)
- end
-
- # Remove directory from repositories storage
- # Every repository inside this directory will be removed too
- #
- # Ex.
- # rm_namespace("gitlab")
- #
- def rm_namespace(name)
- FileUtils.rm_r(full_path(name), force: true)
- end
-
- # Move namespace directory inside repositories storage
- #
- # Ex.
- # mv_namespace("gitlab", "gitlabhq")
- #
- def mv_namespace(old_name, new_name)
- return false if exists?(new_name) || !exists?(old_name)
-
- FileUtils.mv(full_path(old_name), full_path(new_name))
- end
-
- # Remove GitLab Satellites for provided path (namespace or repo dir)
- #
- # Ex.
- # rm_satellites("gitlab")
- #
- # rm_satellites("gitlab/gitlab-ci.git")
- #
- def rm_satellites(path)
- raise ArgumentError.new("Path can't be blank") if path.blank?
-
- satellites_path = File.join(Gitlab.config.satellites.path, path)
- FileUtils.rm_r(satellites_path, force: true)
- end
-
- def url_to_repo path
- Gitlab.config.gitlab_shell.ssh_path_prefix + "#{path}.git"
- end
-
- protected
-
- def gitlab_shell_user_home
- File.expand_path("~#{Gitlab.config.gitlab_shell.ssh_user}")
- end
-
- def repos_path
- Gitlab.config.gitlab_shell.repos_path
- end
-
- def full_path(dir_name)
- raise ArgumentError.new("Directory name can't be blank") if dir_name.blank?
-
- File.join(repos_path, dir_name)
- end
-
- def exists?(dir_name)
- File.exists?(full_path(dir_name))
- end
- end
-end
diff --git a/trustie2/lib/git/backend/shell_adapter.rb b/trustie2/lib/git/backend/shell_adapter.rb
deleted file mode 100644
index f247f4593..000000000
--- a/trustie2/lib/git/backend/shell_adapter.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# == GitLab Shell mixin
-#
-# Provide a shortcut to Gitlab::Shell instance by gitlab_shell
-#
-module Gitlab
- module ShellAdapter
- def gitlab_shell
- Gitlab::Shell.new
- end
- end
-end
-
diff --git a/trustie2/lib/git/backend/shell_env.rb b/trustie2/lib/git/backend/shell_env.rb
deleted file mode 100644
index 157218750..000000000
--- a/trustie2/lib/git/backend/shell_env.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-module Gitlab
- # This module provide 2 methods
- # to set specific ENV variabled for GitLab Shell
- module ShellEnv
- extend self
-
- def set_env(user)
- # Set GL_ID env variable
- ENV['GL_ID'] = "user-#{user.id}"
- end
-
- def reset_env
- # Reset GL_ID env variable
- ENV['GL_ID'] = nil
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/.rspec b/trustie2/lib/plugins/acts-as-taggable-on/.rspec
deleted file mode 100644
index 616c43385..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/.rspec
+++ /dev/null
@@ -1,2 +0,0 @@
---colour
---backtrace
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/.travis.yml b/trustie2/lib/plugins/acts-as-taggable-on/.travis.yml
deleted file mode 100644
index 576396e71..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/.travis.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-script: "cp spec/database.yml.sample spec/database.yml && bundle install && bundle exec rake"
-rvm:
- - 1.8.7
- - 1.9.2
- - 1.9.3
-env:
- - DB=sqlite3
- - DB=mysql
- - DB=postgresql
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/Appraisals b/trustie2/lib/plugins/acts-as-taggable-on/Appraisals
deleted file mode 100644
index ad94b6262..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/Appraisals
+++ /dev/null
@@ -1,7 +0,0 @@
-appraise "rails-3" do
- gem "rails", "3.2.13"
-end
-
-appraise "rails-4" do
- gem "rails", "4.0.0.beta1"
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/Gemfile b/trustie2/lib/plugins/acts-as-taggable-on/Gemfile
deleted file mode 100644
index e37a382a0..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/Gemfile
+++ /dev/null
@@ -1,5 +0,0 @@
-source 'https://rubygems.org'
-
-gemspec
-
-gem 'appraisal'
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/Guardfile b/trustie2/lib/plugins/acts-as-taggable-on/Guardfile
deleted file mode 100644
index 68512309b..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/Guardfile
+++ /dev/null
@@ -1,5 +0,0 @@
-guard 'rspec' do
- watch(%r{^spec/.+_spec\.rb})
- watch(%r{^lib/(.+)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
- watch('spec/spec_helper.rb') { "spec" }
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/LICENSE.md b/trustie2/lib/plugins/acts-as-taggable-on/LICENSE.md
deleted file mode 100644
index 010b7e6e6..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/LICENSE.md
+++ /dev/null
@@ -1,20 +0,0 @@
-__Copyright (c) 2007 Michael Bleigh and Intridea Inc.__
-
-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, title 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.
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/README.md b/trustie2/lib/plugins/acts-as-taggable-on/README.md
deleted file mode 100644
index a67d267ce..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/README.md
+++ /dev/null
@@ -1,303 +0,0 @@
-# ActsAsTaggableOn
-[](http://travis-ci.org/mbleigh/acts-as-taggable-on)
-
-This plugin was originally based on Acts as Taggable on Steroids by Jonathan Viney.
-It has evolved substantially since that point, but all credit goes to him for the
-initial tagging functionality that so many people have used.
-
-For instance, in a social network, a user might have tags that are called skills,
-interests, sports, and more. There is no real way to differentiate between tags and
-so an implementation of this type is not possible with acts as taggable on steroids.
-
-Enter Acts as Taggable On. Rather than tying functionality to a specific keyword
-(namely `tags`), acts as taggable on allows you to specify an arbitrary number of
-tag "contexts" that can be used locally or in combination in the same way steroids
-was used.
-
-## Compatibility
-
-Versions 2.x are compatible with Ruby 1.8.7+ and Rails 3.
-
-Versions 2.4.1 and up are compatible with Rails 4 too (thanks to arabonradar and cwoodcox).
-
-Versions 3.x (currently unreleased) are compatible with Ruby 1.9.3+ and Rails 3 and 4.
-
-For an up-to-date roadmap, see https://github.com/mbleigh/acts-as-taggable-on/issues/milestones
-
-## Installation
-
-To use it, add it to your Gemfile:
-
-```ruby
-gem 'acts-as-taggable-on'
-```
-
-and bundle:
-
-```ruby
-bundle
-```
-
-#### Post Installation
-
-```shell
-rails generate acts_as_taggable_on:migration
-rake db:migrate
-```
-
-## Testing
-
-Acts As Taggable On uses RSpec for its test coverage. Inside the gem
-directory, you can run the specs with:
-
-```shell
-bundle
-rake spec
-```
-
-If you want, add a `.ruby-version` file in the project root (and use rbenv or RVM) to work on a specific version of Ruby.
-
-## Usage
-
-```ruby
-class User < ActiveRecord::Base
- # Alias for acts_as_taggable_on :tags
- acts_as_taggable
- acts_as_taggable_on :skills, :interests
-end
-
-@user = User.new(:name => "Bobby")
-@user.tag_list = "awesome, slick, hefty" # this should be familiar
-@user.skill_list = "joking, clowning, boxing" # but you can do it for any context!
-
-@user.tags # => [,,]
-@user.skills # => [,,]
-@user.skill_list # => ["joking","clowning","boxing"] as TagList
-
-@user.tag_list.remove("awesome") # remove a single tag
-@user.tag_list.remove("awesome, slick") # works with arrays too
-@user.tag_list.add("awesomer") # add a single tag. alias for <<
-@user.tag_list.add("awesomer, slicker") # also works with arrays
-
-User.skill_counts # => [,...]
-```
-
-To preserve the order in which tags are created use `acts_as_ordered_taggable`:
-
-```ruby
-class User < ActiveRecord::Base
- # Alias for acts_as_ordered_taggable_on :tags
- acts_as_ordered_taggable
- acts_as_ordered_taggable_on :skills, :interests
-end
-
-@user = User.new(:name => "Bobby")
-@user.tag_list = "east, south"
-@user.save
-
-@user.tag_list = "north, east, south, west"
-@user.save
-
-@user.reload
-@user.tag_list # => ["north", "east", "south", "west"]
-```
-
-### Finding Tagged Objects
-
-Acts As Taggable On uses scopes to create an association for tags.
-This way you can mix and match to filter down your results.
-
-```ruby
-class User < ActiveRecord::Base
- acts_as_taggable_on :tags, :skills
- scope :by_join_date, order("created_at DESC")
-end
-
-User.tagged_with("awesome").by_join_date
-User.tagged_with("awesome").by_join_date.paginate(:page => params[:page], :per_page => 20)
-
-# Find a user with matching all tags, not just one
-User.tagged_with(["awesome", "cool"], :match_all => true)
-
-# Find a user with any of the tags:
-User.tagged_with(["awesome", "cool"], :any => true)
-
-# Find a user that not tags with awesome or cool:
-User.tagged_with(["awesome", "cool"], :exclude => true)
-
-# Find a user with any of tags based on context:
-User.tagged_with(['awesome, cool'], :on => :tags, :any => true).tagged_with(['smart', 'shy'], :on => :skills, :any => true)
-```
-
-You can also use `:wild => true` option along with `:any` or `:exclude` option. It will looking for `%awesome%` and `%cool%` in sql.
-
-__Tip:__ `User.tagged_with([])` or '' will return `[]`, but not all records.
-
-### Relationships
-
-You can find objects of the same type based on similar tags on certain contexts.
-Also, objects will be returned in descending order based on the total number of
-matched tags.
-
-```ruby
-@bobby = User.find_by_name("Bobby")
-@bobby.skill_list # => ["jogging", "diving"]
-
-@frankie = User.find_by_name("Frankie")
-@frankie.skill_list # => ["hacking"]
-
-@tom = User.find_by_name("Tom")
-@tom.skill_list # => ["hacking", "jogging", "diving"]
-
-@tom.find_related_skills # => [,]
-@bobby.find_related_skills # => []
-@frankie.find_related_skills # => []
-```
-
-### Dynamic Tag Contexts
-
-In addition to the generated tag contexts in the definition, it is also possible
-to allow for dynamic tag contexts (this could be user generated tag contexts!)
-
-```ruby
-@user = User.new(:name => "Bobby")
-@user.set_tag_list_on(:customs, "same, as, tag, list")
-@user.tag_list_on(:customs) # => ["same","as","tag","list"]
-@user.save
-@user.tags_on(:customs) # => [,...]
-@user.tag_counts_on(:customs)
-User.tagged_with("same", :on => :customs) # => [@user]
-```
-
-### Tag Ownership
-
-Tags can have owners:
-
-```ruby
-class User < ActiveRecord::Base
- acts_as_tagger
-end
-
-class Photo < ActiveRecord::Base
- acts_as_taggable_on :locations
-end
-
-@some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations)
-@some_user.owned_taggings
-@some_user.owned_tags
-Photo.tagged_with("paris", :on => :locations, :owned_by => @some_user)
-@some_photo.locations_from(@some_user) # => ["paris", "normandy"]
-@some_photo.owner_tags_on(@some_user, :locations) # => [#...]
-@some_photo.owner_tags_on(nil, :locations) # => Ownerships equivalent to saying @some_photo.locations
-@some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations, :skip_save => true) #won't save @some_photo object
-```
-
-### Dirty objects
-
-```ruby
-@bobby = User.find_by_name("Bobby")
-@bobby.skill_list # => ["jogging", "diving"]
-
-@bobby.skill_list_changed? #=> false
-@bobby.changes #=> {}
-
-@bobby.skill_list = "swimming"
-@bobby.changes.should == {"skill_list"=>["jogging, diving", ["swimming"]]}
-@bobby.skill_list_changed? #=> true
-
-@bobby.skill_list_change.should == ["jogging, diving", ["swimming"]]
-```
-
-### Tag cloud calculations
-
-To construct tag clouds, the frequency of each tag needs to be calculated.
-Because we specified `acts_as_taggable_on` on the `User` class, we can
-get a calculation of all the tag counts by using `User.tag_counts_on(:customs)`. But what if we wanted a tag count for
-an single user's posts? To achieve this we call tag_counts on the association:
-
-```ruby
-User.find(:first).posts.tag_counts_on(:tags)
-```
-
-A helper is included to assist with generating tag clouds.
-
-Here is an example that generates a tag cloud.
-
-Helper:
-
-```ruby
-module PostsHelper
- include ActsAsTaggableOn::TagsHelper
-end
-```
-
-Controller:
-
-```ruby
-class PostController < ApplicationController
- def tag_cloud
- @tags = Post.tag_counts_on(:tags)
- end
-end
-```
-
-View:
-
-```erb
-<% tag_cloud(@tags, %w(css1 css2 css3 css4)) do |tag, css_class| %>
- <%= link_to tag.name, { :action => :tag, :id => tag.name }, :class => css_class %>
-<% end %>
-```
-
-CSS:
-
-```css
-.css1 { font-size: 1.0em; }
-.css2 { font-size: 1.2em; }
-.css3 { font-size: 1.4em; }
-.css4 { font-size: 1.6em; }
-```
-
-## Configuration
-
-If you would like to remove unused tag objects after removing taggings, add:
-
-```ruby
-ActsAsTaggableOn.remove_unused_tags = true
-```
-
-If you want force tags to be saved downcased:
-
-```ruby
-ActsAsTaggableOn.force_lowercase = true
-```
-
-If you want tags to be saved parametrized (you can redefine to_param as well):
-
-```ruby
-ActsAsTaggableOn.force_parameterize = true
-```
-
-If you would like tags to be case-sensitive and not use LIKE queries for creation:
-
-```ruby
-ActsAsTaggableOn.strict_case_match = true
-```
-
-If you want to change the default delimiter (it defaults to ','). You can also pass in an array of delimiters such as ([',', '|']):
-
-```ruby
-ActsAsTaggableOn.delimiter = ','
-```
-
-## Contributors
-
-We have a long list of valued contributors. [Check them all](https://github.com/mbleigh/acts-as-taggable-on/contributors)
-
-## Maintainer
-
-* [Joost Baaij](https://github.com/tilsammans)
-
-## License
-
-See [LICENSE](https://github.com/mbleigh/acts-as-taggable-on/blob/master/LICENSE.md)
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/Rakefile b/trustie2/lib/plugins/acts-as-taggable-on/Rakefile
deleted file mode 100644
index a81fa40d8..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/Rakefile
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'rubygems'
-require 'bundler/setup'
-require 'appraisal'
-
-desc 'Default: run specs'
-task :default => :spec
-
-require 'rspec/core/rake_task'
-RSpec::Core::RakeTask.new do |t|
- t.pattern = "spec/**/*_spec.rb"
-end
-
-Bundler::GemHelper.install_tasks
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/acts-as-taggable-on.gemspec b/trustie2/lib/plugins/acts-as-taggable-on/acts-as-taggable-on.gemspec
deleted file mode 100644
index f4240504a..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/acts-as-taggable-on.gemspec
+++ /dev/null
@@ -1,35 +0,0 @@
-# coding: utf-8
-lib = File.expand_path('../lib', __FILE__)
-$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
-require 'acts_as_taggable_on/version'
-
-Gem::Specification.new do |gem|
- gem.name = "acts-as-taggable-on"
- gem.version = ActsAsTaggableOn::VERSION
- gem.authors = ["Michael Bleigh", "Joost Baaij"]
- gem.email = ["michael@intridea.com", "joost@spacebabies.nl"]
- gem.description = %q{With ActsAsTaggableOn, you can tag a single model on several contexts, such as skills, interests, and awards. It also provides other advanced functionality.}
- gem.summary = "Advanced tagging for Rails."
- gem.homepage = 'https://github.com/mbleigh/acts-as-taggable-on'
- gem.license = "MIT"
-
- gem.files = `git ls-files`.split($/)
- gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
- gem.require_paths = ["lib"]
-
- if File.exists?('UPGRADING')
- gem.post_install_message = File.read('UPGRADING')
- end
-
- gem.add_runtime_dependency 'rails', ['>= 3', '< 5']
-
- gem.add_development_dependency 'rspec-rails', '2.13.0' # 2.13.1 is broken
- gem.add_development_dependency 'rspec', '~> 2.6'
- gem.add_development_dependency 'ammeter'
- gem.add_development_dependency 'sqlite3'
- gem.add_development_dependency 'mysql2', '~> 0.3.7'
- gem.add_development_dependency 'pg'
- gem.add_development_dependency 'guard'
- gem.add_development_dependency 'guard-rspec'
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/gemfiles/rails_3.gemfile b/trustie2/lib/plugins/acts-as-taggable-on/gemfiles/rails_3.gemfile
deleted file mode 100644
index 19f525c52..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/gemfiles/rails_3.gemfile
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-gem "appraisal"
-gem "rails", "3.2.13"
-
-gemspec :path=>"../"
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/gemfiles/rails_4.gemfile b/trustie2/lib/plugins/acts-as-taggable-on/gemfiles/rails_4.gemfile
deleted file mode 100644
index 2bf10158b..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/gemfiles/rails_4.gemfile
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was generated by Appraisal
-
-source "https://rubygems.org"
-
-gem "appraisal"
-gem "rails", :github => 'rails/rails'
-
-gemspec :path=>"../"
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts-as-taggable-on.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts-as-taggable-on.rb
deleted file mode 100644
index 7a6e116c2..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts-as-taggable-on.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-require "active_record"
-require "active_record/version"
-require "action_view"
-
-require "digest/sha1"
-
-$LOAD_PATH.unshift(File.dirname(__FILE__))
-
-module ActsAsTaggableOn
- mattr_accessor :delimiter
- @@delimiter = ','
-
- mattr_accessor :force_lowercase
- @@force_lowercase = false
-
- mattr_accessor :force_parameterize
- @@force_parameterize = false
-
- mattr_accessor :strict_case_match
- @@strict_case_match = false
-
- mattr_accessor :remove_unused_tags
- self.remove_unused_tags = false
-
- def self.glue
- delimiter = @@delimiter.kind_of?(Array) ? @@delimiter[0] : @@delimiter
- delimiter.ends_with?(" ") ? delimiter : "#{delimiter} "
- end
-
- def self.setup
- yield self
- end
-end
-
-
-require "acts_as_taggable_on/utils"
-
-require "acts_as_taggable_on/taggable"
-require "acts_as_taggable_on/acts_as_taggable_on/compatibility"
-require "acts_as_taggable_on/acts_as_taggable_on/core"
-require "acts_as_taggable_on/acts_as_taggable_on/collection"
-require "acts_as_taggable_on/acts_as_taggable_on/cache"
-require "acts_as_taggable_on/acts_as_taggable_on/ownership"
-require "acts_as_taggable_on/acts_as_taggable_on/related"
-require "acts_as_taggable_on/acts_as_taggable_on/dirty"
-
-require "acts_as_taggable_on/tagger"
-require "acts_as_taggable_on/tag"
-require "acts_as_taggable_on/tag_list"
-require "acts_as_taggable_on/tags_helper"
-require "acts_as_taggable_on/tagging"
-
-$LOAD_PATH.shift
-
-
-if defined?(ActiveRecord::Base)
- ActiveRecord::Base.extend ActsAsTaggableOn::Compatibility
- ActiveRecord::Base.extend ActsAsTaggableOn::Taggable
- ActiveRecord::Base.send :include, ActsAsTaggableOn::Tagger
-end
-
-if defined?(ActionView::Base)
- ActionView::Base.send :include, ActsAsTaggableOn::TagsHelper
-end
-
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb
deleted file mode 100644
index 6bec623de..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/cache.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-module ActsAsTaggableOn::Taggable
- module Cache
- def self.included(base)
- # Skip adding caching capabilities if table not exists or no cache columns exist
- return unless base.table_exists? && base.tag_types.any? { |context| base.column_names.include?("cached_#{context.to_s.singularize}_list") }
-
- base.send :include, ActsAsTaggableOn::Taggable::Cache::InstanceMethods
- base.extend ActsAsTaggableOn::Taggable::Cache::ClassMethods
-
- base.class_eval do
- before_save :save_cached_tag_list
- end
-
- base.initialize_acts_as_taggable_on_cache
- end
-
- module ClassMethods
- def initialize_acts_as_taggable_on_cache
- tag_types.map(&:to_s).each do |tag_type|
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def self.caching_#{tag_type.singularize}_list?
- caching_tag_list_on?("#{tag_type}")
- end
- RUBY
- end
- end
-
- def acts_as_taggable_on(*args)
- super(*args)
- initialize_acts_as_taggable_on_cache
- end
-
- def caching_tag_list_on?(context)
- column_names.include?("cached_#{context.to_s.singularize}_list")
- end
- end
-
- module InstanceMethods
- def save_cached_tag_list
- tag_types.map(&:to_s).each do |tag_type|
- if self.class.send("caching_#{tag_type.singularize}_list?")
- if tag_list_cache_set_on(tag_type)
- list = tag_list_cache_on(tag_type).to_a.flatten.compact.join(', ')
- self["cached_#{tag_type.singularize}_list"] = list
- end
- end
- end
-
- true
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb
deleted file mode 100644
index ed49a5218..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/collection.rb
+++ /dev/null
@@ -1,183 +0,0 @@
-module ActsAsTaggableOn::Taggable
- module Collection
- def self.included(base)
- base.send :include, ActsAsTaggableOn::Taggable::Collection::InstanceMethods
- base.extend ActsAsTaggableOn::Taggable::Collection::ClassMethods
- base.initialize_acts_as_taggable_on_collection
- end
-
- module ClassMethods
- def initialize_acts_as_taggable_on_collection
- tag_types.map(&:to_s).each do |tag_type|
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def self.#{tag_type.singularize}_counts(options={})
- tag_counts_on('#{tag_type}', options)
- end
-
- def #{tag_type.singularize}_counts(options = {})
- tag_counts_on('#{tag_type}', options)
- end
-
- def top_#{tag_type}(limit = 10)
- tag_counts_on('#{tag_type}', :order => 'count desc', :limit => limit.to_i)
- end
-
- def self.top_#{tag_type}(limit = 10)
- tag_counts_on('#{tag_type}', :order => 'count desc', :limit => limit.to_i)
- end
- RUBY
- end
- end
-
- def acts_as_taggable_on(*args)
- super(*args)
- initialize_acts_as_taggable_on_collection
- end
-
- def tag_counts_on(context, options = {})
- all_tag_counts(options.merge({:on => context.to_s}))
- end
-
- def tags_on(context, options = {})
- all_tags(options.merge({:on => context.to_s}))
- end
-
- ##
- # Calculate the tag names.
- # To be used when you don't need tag counts and want to avoid the taggable joins.
- #
- # @param [Hash] options Options:
- # * :start_at - Restrict the tags to those created after a certain time
- # * :end_at - Restrict the tags to those created before a certain time
- # * :conditions - A piece of SQL conditions to add to the query. Note we don't join the taggable objects for performance reasons.
- # * :limit - The maximum number of tags to return
- # * :order - A piece of SQL to order by. Eg 'tags.count desc' or 'taggings.created_at desc'
- # * :on - Scope the find to only include a certain context
- def all_tags(options = {})
- options.assert_valid_keys :start_at, :end_at, :conditions, :order, :limit, :on
-
- ## Generate conditions:
- options[:conditions] = sanitize_sql(options[:conditions]) if options[:conditions]
-
- start_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at]
- end_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at]
-
- taggable_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.taggable_type = ?", base_class.name])
- # taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.context = ?", options.delete(:on).to_s]) if options[:on]
-
- tagging_conditions = [
- taggable_conditions,
- start_at_conditions,
- end_at_conditions
- ].compact.reverse
-
- tag_conditions = [
- options[:conditions]
- ].compact.reverse
-
- ## Generate scope:
- tagging_scope = ActsAsTaggableOn::Tagging.select("#{ActsAsTaggableOn::Tagging.table_name}.tag_id")
- tag_scope = ActsAsTaggableOn::Tag.select("#{ActsAsTaggableOn::Tag.table_name}.*").order(options[:order]).limit(options[:limit])
-
- # Joins and conditions
- tagging_conditions.each { |condition| tagging_scope = tagging_scope.where(condition) }
- tag_conditions.each { |condition| tag_scope = tag_scope.where(condition) }
-
- group_columns = "#{ActsAsTaggableOn::Tagging.table_name}.tag_id"
-
- # Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore:
- scoped_select = "#{table_name}.#{primary_key}"
- tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{select(scoped_select).to_sql})").group(group_columns)
-
- tag_scope = tag_scope.joins("JOIN (#{tagging_scope.to_sql}) AS #{ActsAsTaggableOn::Tagging.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.id")
- tag_scope
- end
-
- ##
- # Calculate the tag counts for all tags.
- #
- # @param [Hash] options Options:
- # * :start_at - Restrict the tags to those created after a certain time
- # * :end_at - Restrict the tags to those created before a certain time
- # * :conditions - A piece of SQL conditions to add to the query
- # * :limit - The maximum number of tags to return
- # * :order - A piece of SQL to order by. Eg 'tags.count desc' or 'taggings.created_at desc'
- # * :at_least - Exclude tags with a frequency less than the given value
- # * :at_most - Exclude tags with a frequency greater than the given value
- # * :on - Scope the find to only include a certain context
- def all_tag_counts(options = {})
- options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :on, :id
-
- scope = {}
-
- ## Generate conditions:
- options[:conditions] = sanitize_sql(options[:conditions]) if options[:conditions]
-
- start_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at]
- end_at_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at]
-
- taggable_conditions = sanitize_sql(["#{ActsAsTaggableOn::Tagging.table_name}.taggable_type = ?", base_class.name])
- taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = ?", options[:id]]) if options[:id]
- #taggable_conditions << sanitize_sql([" AND #{ActsAsTaggableOn::Tagging.table_name}.context = ?", options.delete(:on).to_s]) if options[:on]
-
- tagging_conditions = [
- taggable_conditions,
- scope[:conditions],
- start_at_conditions,
- end_at_conditions
- ].compact.reverse
-
- tag_conditions = [
- options[:conditions]
- ].compact.reverse
-
- ## Generate joins:
- taggable_join = "INNER JOIN #{table_name} ON #{table_name}.#{primary_key} = #{ActsAsTaggableOn::Tagging.table_name}.taggable_id"
- taggable_join << " AND #{table_name}.#{inheritance_column} = '#{name}'" unless descends_from_active_record? # Current model is STI descendant, so add type checking to the join condition
-
- tagging_joins = [
- taggable_join,
- scope[:joins]
- ].compact
-
- tag_joins = [
- ].compact
-
- ## Generate scope:
- tagging_scope = ActsAsTaggableOn::Tagging.select("#{ActsAsTaggableOn::Tagging.table_name}.tag_id, COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) AS tags_count")
- tag_scope = ActsAsTaggableOn::Tag.select("#{ActsAsTaggableOn::Tag.table_name}.*, #{ActsAsTaggableOn::Tagging.table_name}.tags_count AS count").order(options[:order]).limit(options[:limit])
-
- # Joins and conditions
- tagging_joins.each { |join| tagging_scope = tagging_scope.joins(join) }
- tagging_conditions.each { |condition| tagging_scope = tagging_scope.where(condition) }
-
- tag_joins.each { |join| tag_scope = tag_scope.joins(join) }
- tag_conditions.each { |condition| tag_scope = tag_scope.where(condition) }
-
- # GROUP BY and HAVING clauses:
- at_least = sanitize_sql(["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) >= ?", options.delete(:at_least)]) if options[:at_least]
- at_most = sanitize_sql(["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) <= ?", options.delete(:at_most)]) if options[:at_most]
- having = ["COUNT(#{ActsAsTaggableOn::Tagging.table_name}.tag_id) > 0", at_least, at_most].compact.join(' AND ')
-
- group_columns = "#{ActsAsTaggableOn::Tagging.table_name}.tag_id"
-
- unless options[:id]
- # Append the current scope to the scope, because we can't use scope(:find) in RoR 3.0 anymore:
- scoped_select = "#{table_name}.#{primary_key}"
- tagging_scope = tagging_scope.where("#{ActsAsTaggableOn::Tagging.table_name}.taggable_id IN(#{select(scoped_select).to_sql})")
- end
-
- tagging_scope = tagging_scope.group(group_columns).having(having)
-
- tag_scope = tag_scope.joins("JOIN (#{tagging_scope.to_sql}) AS #{ActsAsTaggableOn::Tagging.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.id")
- tag_scope
- end
- end
-
- module InstanceMethods
- def tag_counts_on(context, options={})
- self.class.tag_counts_on(context, options.merge(:id => id))
- end
- end
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/compatibility.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/compatibility.rb
deleted file mode 100644
index 488445dcb..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/compatibility.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-module ActsAsTaggableOn::Compatibility
- def has_many_with_compatibility(name, options = {}, &extention)
- if ActiveRecord::VERSION::MAJOR >= 4
- scope, opts = build_scope_and_options(options)
- has_many(name, scope, opts, &extention)
- else
- has_many(name, options, &extention)
- end
- end
-
- def build_scope_and_options(opts)
- scope_opts, opts = parse_options(opts)
-
- unless scope_opts.empty?
- scope = lambda do
- scope_opts.inject(self) { |result, hash| result.send *hash } ##原来代码用的是 *hash
- end
- end
-
- [defined?(scope) ? scope : nil, opts]
- end
-
- def parse_options(opts)
- scope_opts = {}
- [:order, :having, :select, :group, :limit, :offset, :readonly].each do |o|
- scope_opts[o] = opts.delete o if opts[o]
- end
- scope_opts[:where] = opts.delete :conditions if opts[:conditions]
- scope_opts[:joins] = opts.delete :include if opts [:include]
- scope_opts[:distinct] = opts.delete :uniq if opts[:uniq]
-
- [scope_opts, opts]
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb
deleted file mode 100644
index 8ca6962fd..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/core.rb
+++ /dev/null
@@ -1,388 +0,0 @@
-module ActsAsTaggableOn::Taggable
- module Core
- def self.included(base)
- base.send :include, ActsAsTaggableOn::Taggable::Core::InstanceMethods
- base.extend ActsAsTaggableOn::Taggable::Core::ClassMethods
-
- base.class_eval do
- attr_writer :custom_contexts
- after_save :save_tags
- end
-
- base.initialize_acts_as_taggable_on_core
- end
-
- module ClassMethods
-
- def initialize_acts_as_taggable_on_core
- include taggable_mixin
- tag_types.map(&:to_s).each do |tags_type|
- tag_type = tags_type.to_s.singularize
- context_taggings = "#{tag_type}_taggings".to_sym
- context_tags = tags_type.to_sym
- taggings_order = (preserve_tag_order? ? "#{ActsAsTaggableOn::Tagging.table_name}.id" : [])
-
- class_eval do
- # when preserving tag order, include order option so that for a 'tags' context
- # the associations tag_taggings & tags are always returned in created order
- has_many_with_compatibility context_taggings, :as => :taggable,
- :dependent => :destroy,
- :class_name => "ActsAsTaggableOn::Tagging",
- :order => taggings_order,
- :conditions => ["#{ActsAsTaggableOn::Tagging.table_name}.context = (?)", tags_type],
- :include => :tag
-
- has_many_with_compatibility context_tags, :through => context_taggings,
- :source => :tag,
- :class_name => "ActsAsTaggableOn::Tag",
- :order => taggings_order
-
- end
-
- taggable_mixin.class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{tag_type}_list
- tag_list_on('#{tags_type}')
- end
-
- def #{tag_type}_list=(new_tags)
- set_tag_list_on('#{tags_type}', new_tags)
- end
-
- def all_#{tags_type}_list
- all_tags_list_on('#{tags_type}')
- end
- RUBY
- end
- end
-
- def taggable_on(preserve_tag_order, *tag_types)
- super(preserve_tag_order, *tag_types)
- initialize_acts_as_taggable_on_core
- end
-
- # all column names are necessary for PostgreSQL group clause
- def grouped_column_names_for(object)
- object.column_names.map { |column| "#{object.table_name}.#{column}" }.join(", ")
- end
-
- ##
- # Return a scope of objects that are tagged with the specified tags.
- #
- # @param tags The tags that we want to query for
- # @param [Hash] options A hash of options to alter you query:
- # * :exclude - if set to true, return objects that are *NOT* tagged with the specified tags
- # * :any - if set to true, return objects that are tagged with *ANY* of the specified tags
- # * :match_all - if set to true, return objects that are *ONLY* tagged with the specified tags
- # * :owned_by - return objects that are *ONLY* owned by the owner
- #
- # Example:
- # User.tagged_with("awesome", "cool") # Users that are tagged with awesome and cool
- # User.tagged_with("awesome", "cool", :exclude => true) # Users that are not tagged with awesome or cool
- # User.tagged_with("awesome", "cool", :any => true) # Users that are tagged with awesome or cool
- # User.tagged_with("awesome", "cool", :match_all => true) # Users that are tagged with just awesome and cool
- # User.tagged_with("awesome", "cool", :owned_by => foo ) # Users that are tagged with just awesome and cool by 'foo'
- def tagged_with(tags, options = {})
- tag_list = ActsAsTaggableOn::TagList.from(tags)
- empty_result = where("1 = 0")
-
- return empty_result if tag_list.empty?
-
- joins = []
- conditions = []
- having = []
- select_clause = []
-
- context = options.delete(:on)
- owned_by = options.delete(:owned_by)
- alias_base_name = undecorated_table_name.gsub('.','_')
- quote = ActsAsTaggableOn::Tag.using_postgresql? ? '"' : ''
-
- if options.delete(:exclude)
- if options.delete(:wild)
- tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ? ESCAPE '!'", "%#{escape_like(t)}%"]) }.join(" OR ")
- else
- tags_conditions = tag_list.map { |t| sanitize_sql(["#{ActsAsTaggableOn::Tag.table_name}.name #{like_operator} ?", t]) }.join(" OR ")
- end
-
- conditions << "#{table_name}.#{primary_key} NOT IN (SELECT #{ActsAsTaggableOn::Tagging.table_name}.taggable_id FROM #{ActsAsTaggableOn::Tagging.table_name} JOIN #{ActsAsTaggableOn::Tag.table_name} ON #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND (#{tags_conditions}) WHERE #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name)})"
-
- if owned_by
- joins << "JOIN #{ActsAsTaggableOn::Tagging.table_name}" +
- " ON #{ActsAsTaggableOn::Tagging.table_name}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
- " AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = #{quote_value(base_class.name)}" +
- " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_id = #{owned_by.id}" +
- " AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_type = #{quote_value(owned_by.class.base_class.to_s)}"
- end
-
- elsif options.delete(:any)
- # get tags, drop out if nothing returned (we need at least one)
- tags = if options.delete(:wild)
- ActsAsTaggableOn::Tag.named_like_any(tag_list)
- else
- ActsAsTaggableOn::Tag.named_any(tag_list)
- end
-
- return empty_result unless tags.length > 0
-
- # setup taggings alias so we can chain, ex: items_locations_taggings_awesome_cool_123
- # avoid ambiguous column name
- taggings_context = context ? "_#{context}" : ''
-
- taggings_alias = adjust_taggings_alias(
- "#{alias_base_name[0..4]}#{taggings_context[0..6]}_taggings_#{sha_prefix(tags.map(&:name).join('_'))}"
- )
-
- tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
- " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
- " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}"
- tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
-
- # don't need to sanitize sql, map all ids and join with OR logic
- conditions << tags.map { |t| "#{taggings_alias}.tag_id = #{t.id}" }.join(" OR ")
- select_clause = "DISTINCT #{table_name}.*" unless context and tag_types.one?
-
- if owned_by
- tagging_join << " AND " +
- sanitize_sql([
- "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
- owned_by.id,
- owned_by.class.base_class.to_s
- ])
- end
-
- joins << tagging_join
- else
- tags = ActsAsTaggableOn::Tag.named_any(tag_list)
-
- return empty_result unless tags.length == tag_list.length
-
- tags.each do |tag|
- taggings_alias = adjust_taggings_alias("#{alias_base_name[0..11]}_taggings_#{sha_prefix(tag.name)}")
- tagging_join = "JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
- " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
- " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}" +
- " AND #{taggings_alias}.tag_id = #{tag.id}"
-
- tagging_join << " AND " + sanitize_sql(["#{taggings_alias}.context = ?", context.to_s]) if context
-
- if owned_by
- tagging_join << " AND " +
- sanitize_sql([
- "#{taggings_alias}.tagger_id = ? AND #{taggings_alias}.tagger_type = ?",
- owned_by.id,
- owned_by.class.base_class.to_s
- ])
- end
-
- joins << tagging_join
- end
- end
-
- taggings_alias, tags_alias = adjust_taggings_alias("#{alias_base_name}_taggings_group"), "#{alias_base_name}_tags_group"
-
- if options.delete(:match_all)
- joins << "LEFT OUTER JOIN #{ActsAsTaggableOn::Tagging.table_name} #{taggings_alias}" +
- " ON #{taggings_alias}.taggable_id = #{quote}#{table_name}#{quote}.#{primary_key}" +
- " AND #{taggings_alias}.taggable_type = #{quote_value(base_class.name)}"
-
-
- group_columns = ActsAsTaggableOn::Tag.using_postgresql? ? grouped_column_names_for(self) : "#{table_name}.#{primary_key}"
- group = group_columns
- having = "COUNT(#{taggings_alias}.taggable_id) = #{tags.size}"
- end
-
- select(select_clause) \
- .joins(joins.join(" ")) \
- .where(conditions.join(" AND ")) \
- .group(group) \
- .having(having) \
- .order(options[:order]) \
- .readonly(false)
- end
-
- def is_taggable?
- true
- end
-
- def adjust_taggings_alias(taggings_alias)
- if taggings_alias.size > 75
- taggings_alias = 'taggings_alias_' + Digest::SHA1.hexdigest(taggings_alias)
- end
- taggings_alias
- end
-
- def taggable_mixin
- @taggable_mixin ||= Module.new
- end
- end
-
- module InstanceMethods
- # all column names are necessary for PostgreSQL group clause
- def grouped_column_names_for(object)
- self.class.grouped_column_names_for(object)
- end
-
- def custom_contexts
- @custom_contexts ||= []
- end
-
- def is_taggable?
- self.class.is_taggable?
- end
-
- def add_custom_context(value)
- custom_contexts << value.to_s unless custom_contexts.include?(value.to_s) or self.class.tag_types.map(&:to_s).include?(value.to_s)
- end
-
- def cached_tag_list_on(context)
- self["cached_#{context.to_s.singularize}_list"]
- end
-
- def tag_list_cache_set_on(context)
- variable_name = "@#{context.to_s.singularize}_list"
- instance_variable_defined?(variable_name) && !instance_variable_get(variable_name).nil?
- end
-
- def tag_list_cache_on(context)
- variable_name = "@#{context.to_s.singularize}_list"
- if instance_variable_get(variable_name)
- instance_variable_get(variable_name)
- elsif cached_tag_list_on(context) && self.class.caching_tag_list_on?(context)
- instance_variable_set(variable_name, ActsAsTaggableOn::TagList.from(cached_tag_list_on(context)))
- else
- instance_variable_set(variable_name, ActsAsTaggableOn::TagList.new(tags_on(context).map(&:name)))
- end
- end
-
- def tag_list_on(context)
- add_custom_context(context)
- tag_list_cache_on(context)
- end
-
- def all_tags_list_on(context)
- variable_name = "@all_#{context.to_s.singularize}_list"
- return instance_variable_get(variable_name) if instance_variable_defined?(variable_name) && instance_variable_get(variable_name)
-
- instance_variable_set(variable_name, ActsAsTaggableOn::TagList.new(all_tags_on(context).map(&:name)).freeze)
- end
-
- ##
- # Returns all tags of a given context
- def all_tags_on(context)
- tag_table_name = ActsAsTaggableOn::Tag.table_name
- tagging_table_name = ActsAsTaggableOn::Tagging.table_name
-
- opts = ["#{tagging_table_name}.context = ?", context.to_s]
- scope = base_tags.where(opts)
-
- if ActsAsTaggableOn::Tag.using_postgresql?
- group_columns = grouped_column_names_for(ActsAsTaggableOn::Tag)
- scope.order("max(#{tagging_table_name}.created_at)").group(group_columns)
- else
- scope.group("#{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key}")
- end.to_a
- end
-
- ##
- # Returns all tags that are not owned of a given context
- def tags_on(context)
- scope = base_tags.where(["#{ActsAsTaggableOn::Tagging.table_name}.context = ? AND #{ActsAsTaggableOn::Tagging.table_name}.tagger_id IS NULL", context.to_s])
- # when preserving tag order, return tags in created order
- # if we added the order to the association this would always apply
- scope = scope.order("#{ActsAsTaggableOn::Tagging.table_name}.id") if self.class.preserve_tag_order?
- scope
- end
-
- def set_tag_list_on(context, new_list)
- add_custom_context(context)
-
- variable_name = "@#{context.to_s.singularize}_list"
- process_dirty_object(context, new_list) unless custom_contexts.include?(context.to_s)
-
- instance_variable_set(variable_name, ActsAsTaggableOn::TagList.from(new_list))
- end
-
- def tagging_contexts
- custom_contexts + self.class.tag_types.map(&:to_s)
- end
-
- def process_dirty_object(context,new_list)
- value = new_list.is_a?(Array) ? new_list.join(', ') : new_list
- attrib = "#{context.to_s.singularize}_list"
-
- if changed_attributes.include?(attrib)
- # The attribute already has an unsaved change.
- old = changed_attributes[attrib]
- changed_attributes.delete(attrib) if (old.to_s == value.to_s)
- else
- old = tag_list_on(context).to_s
- changed_attributes[attrib] = old if (old.to_s != value.to_s)
- end
- end
-
- def reload(*args)
- self.class.tag_types.each do |context|
- instance_variable_set("@#{context.to_s.singularize}_list", nil)
- instance_variable_set("@all_#{context.to_s.singularize}_list", nil)
- end
-
- super(*args)
- end
-
- def save_tags
- tagging_contexts.each do |context|
- next unless tag_list_cache_set_on(context)
- # List of currently assigned tag names
- tag_list = tag_list_cache_on(context).uniq
-
- # Find existing tags or create non-existing tags:
- tags = ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name(tag_list)
-
- # Tag objects for currently assigned tags
- current_tags = tags_on(context)
-
- # Tag maintenance based on whether preserving the created order of tags
- if self.class.preserve_tag_order?
- old_tags, new_tags = current_tags - tags, tags - current_tags
-
- shared_tags = current_tags & tags
-
- if shared_tags.any? && tags[0...shared_tags.size] != shared_tags
- index = shared_tags.each_with_index { |_, i| break i unless shared_tags[i] == tags[i] }
-
- # Update arrays of tag objects
- old_tags |= current_tags[index...current_tags.size]
- new_tags |= current_tags[index...current_tags.size] & shared_tags
-
- # Order the array of tag objects to match the tag list
- new_tags = tags.map do |t|
- new_tags.find { |n| n.name.downcase == t.name.downcase }
- end.compact
- end
- else
- # Delete discarded tags and create new tags
- old_tags = current_tags - tags
- new_tags = tags - current_tags
- end
-
- # Find taggings to remove:
- if old_tags.present?
- old_taggings = taggings.where(:tagger_type => nil, :tagger_id => nil, :context => context.to_s, :tag_id => old_tags)
- end
-
- # Destroy old taggings:
- if old_taggings.present?
- ActsAsTaggableOn::Tagging.destroy_all "#{ActsAsTaggableOn::Tagging.primary_key}".to_sym => old_taggings.map(&:id)
- end
-
- # Create new taggings:
- new_tags.each do |tag|
- taggings.create!(:tag_id => tag.id, :context => context.to_s, :taggable => self)
- end
- end
-
- true
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb
deleted file mode 100644
index 2bc036842..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-module ActsAsTaggableOn::Taggable
- module Dirty
- def self.included(base)
- base.extend ActsAsTaggableOn::Taggable::Dirty::ClassMethods
-
- base.initialize_acts_as_taggable_on_dirty
- end
-
- module ClassMethods
- def initialize_acts_as_taggable_on_dirty
- tag_types.map(&:to_s).each do |tags_type|
- tag_type = tags_type.to_s.singularize
- context_tags = tags_type.to_sym
-
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{tag_type}_list_changed?
- changed_attributes.include?("#{tag_type}_list")
- end
-
- def #{tag_type}_list_was
- changed_attributes.include?("#{tag_type}_list") ? changed_attributes["#{tag_type}_list"] : __send__("#{tag_type}_list")
- end
-
- def #{tag_type}_list_change
- [changed_attributes['#{tag_type}_list'], __send__('#{tag_type}_list')] if changed_attributes.include?("#{tag_type}_list")
- end
-
- def #{tag_type}_list_changes
- [changed_attributes['#{tag_type}_list'], __send__('#{tag_type}_list')] if changed_attributes.include?("#{tag_type}_list")
- end
- RUBY
-
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb
deleted file mode 100644
index 007d959ed..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/ownership.rb
+++ /dev/null
@@ -1,135 +0,0 @@
-module ActsAsTaggableOn::Taggable
- module Ownership
- def self.included(base)
- base.send :include, ActsAsTaggableOn::Taggable::Ownership::InstanceMethods
- base.extend ActsAsTaggableOn::Taggable::Ownership::ClassMethods
-
- base.class_eval do
- after_save :save_owned_tags
- end
-
- base.initialize_acts_as_taggable_on_ownership
- end
-
- module ClassMethods
- def acts_as_taggable_on(*args)
- initialize_acts_as_taggable_on_ownership
- super(*args)
- end
-
- def initialize_acts_as_taggable_on_ownership
- tag_types.map(&:to_s).each do |tag_type|
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def #{tag_type}_from(owner)
- owner_tag_list_on(owner, '#{tag_type}')
- end
- RUBY
- end
- end
- end
-
- module InstanceMethods
- def owner_tags_on(owner, context)
- if owner.nil?
- scope = base_tags.where([%(#{ActsAsTaggableOn::Tagging.table_name}.context = ?), context.to_s, 10])
- else
- scope = base_tags.where([%(#{ActsAsTaggableOn::Tagging.table_name}.context = ? AND
- #{ActsAsTaggableOn::Tagging.table_name}.tagger_id = ? AND
- #{ActsAsTaggableOn::Tagging.table_name}.tagger_type = ?), context.to_s, owner.id, owner.class.base_class.to_s, 10])
- end
-
- # when preserving tag order, return tags in created order
- # if we added the order to the association this would always apply
- if self.class.preserve_tag_order?
- scope.order("#{ActsAsTaggableOn::Tagging.table_name}.id")
- else
- scope
- end
- end
-
- def cached_owned_tag_list_on(context)
- variable_name = "@owned_#{context}_list"
- cache = (instance_variable_defined?(variable_name) && instance_variable_get(variable_name)) || instance_variable_set(variable_name, {})
- end
-
- def owner_tag_list_on(owner, context)
- add_custom_context(context)
-
- cache = cached_owned_tag_list_on(context)
-
- cache[owner] ||= ActsAsTaggableOn::TagList.new(*owner_tags_on(owner, context).map(&:name))
- end
-
- def set_owner_tag_list_on(owner, context, new_list)
- add_custom_context(context)
-
- cache = cached_owned_tag_list_on(context)
-
- cache[owner] = ActsAsTaggableOn::TagList.from(new_list)
- end
-
- def reload(*args)
- self.class.tag_types.each do |context|
- instance_variable_set("@owned_#{context}_list", nil)
- end
-
- super(*args)
- end
-
- def save_owned_tags
- tagging_contexts.each do |context|
- cached_owned_tag_list_on(context).each do |owner, tag_list|
-
- # Find existing tags or create non-existing tags:
- tags = ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name(tag_list.uniq)
-
- # Tag objects for owned tags
- owned_tags = owner_tags_on(owner, context)
-
- # Tag maintenance based on whether preserving the created order of tags
- if self.class.preserve_tag_order?
- old_tags, new_tags = owned_tags - tags, tags - owned_tags
-
- shared_tags = owned_tags & tags
-
- if shared_tags.any? && tags[0...shared_tags.size] != shared_tags
- index = shared_tags.each_with_index { |_, i| break i unless shared_tags[i] == tags[i] }
-
- # Update arrays of tag objects
- old_tags |= owned_tags.from(index)
- new_tags |= owned_tags.from(index) & shared_tags
-
- # Order the array of tag objects to match the tag list
- new_tags = tags.map { |t| new_tags.find { |n| n.name.downcase == t.name.downcase } }.compact
- end
- else
- # Delete discarded tags and create new tags
- old_tags = owned_tags - tags
- new_tags = tags - owned_tags
- end
-
- # Find all taggings that belong to the taggable (self), are owned by the owner,
- # have the correct context, and are removed from the list.
- if old_tags.present?
- old_taggings = ActsAsTaggableOn::Tagging.where(:taggable_id => id, :taggable_type => self.class.base_class.to_s,
- :tagger_type => owner.class.base_class.to_s, :tagger_id => owner.id,
- :tag_id => old_tags, :context => context)
- end
-
- # Destroy old taggings:
- if old_taggings.present?
- ActsAsTaggableOn::Tagging.destroy_all(:id => old_taggings.map(&:id))
- end
-
- # Create new taggings:
- new_tags.each do |tag|
- taggings.create!(:tag_id => tag.id, :context => context.to_s, :tagger => owner, :taggable => self)
- end
- end
- end
-
- true
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb
deleted file mode 100644
index 98f3d3c2f..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/acts_as_taggable_on/related.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-module ActsAsTaggableOn::Taggable
- module Related
- def self.included(base)
- base.send :include, ActsAsTaggableOn::Taggable::Related::InstanceMethods
- base.extend ActsAsTaggableOn::Taggable::Related::ClassMethods
- base.initialize_acts_as_taggable_on_related
- end
-
- module ClassMethods
- def initialize_acts_as_taggable_on_related
- tag_types.map(&:to_s).each do |tag_type|
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def find_related_#{tag_type}(options = {})
- related_tags_for('#{tag_type}', self.class, options)
- end
- alias_method :find_related_on_#{tag_type}, :find_related_#{tag_type}
-
- def find_related_#{tag_type}_for(klass, options = {})
- related_tags_for('#{tag_type}', klass, options)
- end
- RUBY
- end
-
- unless tag_types.empty?
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def find_matching_contexts(search_context, result_context, options = {})
- matching_contexts_for(search_context.to_s, result_context.to_s, self.class, options)
- end
-
- def find_matching_contexts_for(klass, search_context, result_context, options = {})
- matching_contexts_for(search_context.to_s, result_context.to_s, klass, options)
- end
- RUBY
- end
- end
-
- def acts_as_taggable_on(*args)
- super(*args)
- initialize_acts_as_taggable_on_related
- end
- end
-
- module InstanceMethods
- def matching_contexts_for(search_context, result_context, klass, options = {})
- tags_to_find = tags_on(search_context).collect { |t| t.name }
-
- klass.select("#{klass.table_name}.*, COUNT(#{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key}) AS count") \
- .from("#{klass.table_name}, #{ActsAsTaggableOn::Tag.table_name}, #{ActsAsTaggableOn::Tagging.table_name}") \
- .where(["#{exclude_self(klass, id)} #{klass.table_name}.#{klass.primary_key} = #{ActsAsTaggableOn::Tagging.table_name}.taggable_id AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = '#{klass.base_class.to_s}' AND #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND #{ActsAsTaggableOn::Tag.table_name}.name IN (?) AND #{ActsAsTaggableOn::Tagging.table_name}.context = ?", tags_to_find, result_context]) \
- .group(group_columns(klass)) \
- .order("count DESC")
- end
-
- def related_tags_for(context, klass, options = {})
- tags_to_ignore = Array.wrap(options.delete(:ignore)).map(&:to_s) || []
- tags_to_find = tags_on(context).collect { |t| t.name }.reject { |t| tags_to_ignore.include? t }
-
- klass.select("#{klass.table_name}.*, COUNT(#{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key}) AS count") \
- .from("#{klass.table_name}, #{ActsAsTaggableOn::Tag.table_name}, #{ActsAsTaggableOn::Tagging.table_name}") \
- .where(["#{exclude_self(klass, id)} #{klass.table_name}.#{klass.primary_key} = #{ActsAsTaggableOn::Tagging.table_name}.taggable_id AND #{ActsAsTaggableOn::Tagging.table_name}.taggable_type = '#{klass.base_class.to_s}' AND #{ActsAsTaggableOn::Tagging.table_name}.tag_id = #{ActsAsTaggableOn::Tag.table_name}.#{ActsAsTaggableOn::Tag.primary_key} AND #{ActsAsTaggableOn::Tag.table_name}.name IN (?)", tags_to_find]) \
- .group(group_columns(klass)) \
- .order("count DESC")
- end
-
- private
-
- def exclude_self(klass, id)
- if [self.class.base_class, self.class].include? klass
- "#{klass.table_name}.#{klass.primary_key} != #{id} AND"
- else
- nil
- end
- end
-
- def group_columns(klass)
- if ActsAsTaggableOn::Tag.using_postgresql?
- grouped_column_names_for(klass)
- else
- "#{klass.table_name}.#{klass.primary_key}"
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tag.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tag.rb
deleted file mode 100644
index 07bbb6ca7..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tag.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-module ActsAsTaggableOn
- class Tag < ::ActiveRecord::Base
- include ActsAsTaggableOn::Utils
-
- attr_accessible :name if defined?(ActiveModel::MassAssignmentSecurity)
-
- ### ASSOCIATIONS:
-
- has_many :taggings, :dependent => :destroy, :class_name => 'ActsAsTaggableOn::Tagging'
-
- ### VALIDATIONS:
-
- validates_presence_of :name
- validates_uniqueness_of :name, :if => :validates_name_uniqueness?
- validates_length_of :name, :maximum => 255
-
- # monkey patch this method if don't need name uniqueness validation
- def validates_name_uniqueness?
- true
- end
-
- ### SCOPES:
-
- def self.named(name)
- if ActsAsTaggableOn.strict_case_match
- where(["name = #{binary}?", name])
- else
- where(["lower(name) = ?", name.downcase])
- end
- end
-
- def self.named_any(list)
- if ActsAsTaggableOn.strict_case_match
- where(list.map { |tag| sanitize_sql(["name = #{binary}?", tag.to_s.mb_chars]) }.join(" OR "))
- else
- where(list.map { |tag| sanitize_sql(["lower(name) = ?", tag.to_s.mb_chars.downcase]) }.join(" OR "))
- end
- end
-
- def self.named_like(name)
- where(["name #{like_operator} ? ESCAPE '!'", "%#{escape_like(name)}%"])
- end
-
- def self.named_like_any(list)
- where(list.map { |tag| sanitize_sql(["name #{like_operator} ? ESCAPE '!'", "%#{escape_like(tag.to_s)}%"]) }.join(" OR "))
- end
-
- ### CLASS METHODS:
-
- def self.find_or_create_with_like_by_name(name)
- if (ActsAsTaggableOn.strict_case_match)
- self.find_or_create_all_with_like_by_name([name]).first
- else
- named_like(name).first || create(:name => name)
- end
- end
-
- def self.find_or_create_all_with_like_by_name(*list)
- list = [list].flatten
-
- return [] if list.empty?
-
- existing_tags = Tag.named_any(list)
-
- list.map do |tag_name|
- comparable_tag_name = comparable_name(tag_name)
- existing_tag = existing_tags.find { |tag| comparable_name(tag.name) == comparable_tag_name }
-
- existing_tag || Tag.create(:name => tag_name)
- end
- end
-
- ### INSTANCE METHODS:
-
- def ==(object)
- super || (object.is_a?(Tag) && name == object.name)
- end
-
- def to_s
- name
- end
-
- def count
- read_attribute(:count).to_i
- end
-
- class << self
- private
-
- def comparable_name(str)
- str.mb_chars.downcase.to_s
- end
-
- def binary
- /mysql/ === ActiveRecord::Base.connection_config[:adapter] ? "BINARY " : nil
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tag_list.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tag_list.rb
deleted file mode 100644
index 0eb39ebf2..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tag_list.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-require 'active_support/core_ext/module/delegation'
-
-module ActsAsTaggableOn
- class TagList < Array
- attr_accessor :owner
-
- def initialize(*args)
- add(*args)
- end
-
- ##
- # Returns a new TagList using the given tag string.
- #
- # Example:
- # tag_list = TagList.from("One , Two, Three")
- # tag_list # ["One", "Two", "Three"]
- def self.from(string)
- string = string.join(ActsAsTaggableOn.glue) if string.respond_to?(:join)
-
- new.tap do |tag_list|
- string = string.to_s.dup
-
- # Parse the quoted tags
- d = ActsAsTaggableOn.delimiter
- d = d.join("|") if d.kind_of?(Array)
- string.gsub!(/(\A|#{d})\s*"(.*?)"\s*(#{d}\s*|\z)/) { tag_list << $2; $3 }
- string.gsub!(/(\A|#{d})\s*'(.*?)'\s*(#{d}\s*|\z)/) { tag_list << $2; $3 }
-
- tag_list.add(string.split(Regexp.new d))
- end
- end
-
- ##
- # Add tags to the tag_list. Duplicate or blank tags will be ignored.
- # Use the :parse option to add an unparsed tag string.
- #
- # Example:
- # tag_list.add("Fun", "Happy")
- # tag_list.add("Fun, Happy", :parse => true)
- def add(*names)
- extract_and_apply_options!(names)
- concat(names)
- clean!
- self
- end
-
- ##
- # Remove specific tags from the tag_list.
- # Use the :parse option to add an unparsed tag string.
- #
- # Example:
- # tag_list.remove("Sad", "Lonely")
- # tag_list.remove("Sad, Lonely", :parse => true)
- def remove(*names)
- extract_and_apply_options!(names)
- delete_if { |name| names.include?(name) }
- self
- end
-
- ##
- # Transform the tag_list into a tag string suitable for editing in a form.
- # The tags are joined with TagList.delimiter and quoted if necessary.
- #
- # Example:
- # tag_list = TagList.new("Round", "Square,Cube")
- # tag_list.to_s # 'Round, "Square,Cube"'
- def to_s
- tags = frozen? ? self.dup : self
- tags.send(:clean!)
-
- tags.map do |name|
- d = ActsAsTaggableOn.delimiter
- d = Regexp.new d.join("|") if d.kind_of? Array
- name.index(d) ? "\"#{name}\"" : name
- end.join(ActsAsTaggableOn.glue)
- end
-
- private
-
- # Remove whitespace, duplicates, and blanks.
- def clean!
- reject!(&:blank?)
- map!(&:strip)
- map!{ |tag| tag.mb_chars.downcase.to_s } if ActsAsTaggableOn.force_lowercase
- map!(&:parameterize) if ActsAsTaggableOn.force_parameterize
-
- uniq!
- end
-
- def extract_and_apply_options!(args)
- options = args.last.is_a?(Hash) ? args.pop : {}
- options.assert_valid_keys :parse
-
- if options[:parse]
- args.map! { |a| self.class.from(a) }
- end
-
- args.flatten!
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/taggable.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/taggable.rb
deleted file mode 100644
index a616bcb5d..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/taggable.rb
+++ /dev/null
@@ -1,105 +0,0 @@
-module ActsAsTaggableOn
- module Taggable
- def taggable?
- false
- end
-
- ##
- # This is an alias for calling acts_as_taggable_on :tags.
- #
- # Example:
- # class Book < ActiveRecord::Base
- # acts_as_taggable
- # end
- def acts_as_taggable
- acts_as_taggable_on :tags
- end
-
- ##
- # This is an alias for calling acts_as_ordered_taggable_on :tags.
- #
- # Example:
- # class Book < ActiveRecord::Base
- # acts_as_ordered_taggable
- # end
- def acts_as_ordered_taggable
- acts_as_ordered_taggable_on :tags
- end
-
- ##
- # Make a model taggable on specified contexts.
- #
- # @param [Array] tag_types An array of taggable contexts
- #
- # Example:
- # class User < ActiveRecord::Base
- # acts_as_taggable_on :languages, :skills
- # end
- def acts_as_taggable_on(*tag_types)
- taggable_on(false, tag_types)
- end
-
-
- ##
- # Make a model taggable on specified contexts
- # and preserves the order in which tags are created
- #
- # @param [Array] tag_types An array of taggable contexts
- #
- # Example:
- # class User < ActiveRecord::Base
- # acts_as_ordered_taggable_on :languages, :skills
- # end
- def acts_as_ordered_taggable_on(*tag_types)
- taggable_on(true, tag_types)
- end
-
- private
-
- # Make a model taggable on specified contexts
- # and optionally preserves the order in which tags are created
- #
- # Seperate methods used above for backwards compatibility
- # so that the original acts_as_taggable_on method is unaffected
- # as it's not possible to add another arguement to the method
- # without the tag_types being enclosed in square brackets
- #
- # NB: method overridden in core module in order to create tag type
- # associations and methods after this logic has executed
- #
- def taggable_on(preserve_tag_order, *tag_types)
- tag_types = tag_types.to_a.flatten.compact.map(&:to_sym)
-
- if taggable?
- self.tag_types = (self.tag_types + tag_types).uniq
- self.preserve_tag_order = preserve_tag_order
- else
- class_attribute :tag_types
- self.tag_types = tag_types
- class_attribute :preserve_tag_order
- self.preserve_tag_order = preserve_tag_order
-
- class_eval do
- has_many :taggings, :as => :taggable, :dependent => :destroy, :class_name => "ActsAsTaggableOn::Tagging"
- has_many :base_tags, :through => :taggings, :source => :tag, :class_name => "ActsAsTaggableOn::Tag"
-
- def self.taggable?
- true
- end
-
- include ActsAsTaggableOn::Utils
- end
- end
-
- # each of these add context-specific methods and must be
- # called on each call of taggable_on
- include ActsAsTaggableOn::Taggable::Core
- include ActsAsTaggableOn::Taggable::Collection
- include ActsAsTaggableOn::Taggable::Cache
- include ActsAsTaggableOn::Taggable::Ownership
- include ActsAsTaggableOn::Taggable::Related
- include ActsAsTaggableOn::Taggable::Dirty
- end
-
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tagger.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tagger.rb
deleted file mode 100644
index bb148e36c..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tagger.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-module ActsAsTaggableOn
- module Tagger
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- ##
- # Make a model a tagger. This allows an instance of a model to claim ownership
- # of tags.
- #
- # Example:
- # class User < ActiveRecord::Base
- # acts_as_tagger
- # end
- def acts_as_tagger(opts={})
- class_eval do
- has_many_with_compatibility :owned_taggings,
- opts.merge(
- :as => :tagger,
- :dependent => :destroy,
- :class_name => "ActsAsTaggableOn::Tagging"
- )
-
- has_many_with_compatibility :owned_tags,
- :through => :owned_taggings,
- :source => :tag,
- :class_name => "ActsAsTaggableOn::Tag",
- :uniq => true
- end
-
- include ActsAsTaggableOn::Tagger::InstanceMethods
- extend ActsAsTaggableOn::Tagger::SingletonMethods
- end
-
- def is_tagger?
- false
- end
- end
-
- module InstanceMethods
- ##
- # Tag a taggable model with tags that are owned by the tagger.
- #
- # @param taggable The object that will be tagged
- # @param [Hash] options An hash with options. Available options are:
- # * :with - The tags that you want to
- # * :on - The context on which you want to tag
- #
- # Example:
- # @user.tag(@photo, :with => "paris, normandy", :on => :locations)
- def tag(taggable, opts={})
- opts.reverse_merge!(:force => true)
- skip_save = opts.delete(:skip_save)
- return false unless taggable.respond_to?(:is_taggable?) && taggable.is_taggable?
-
- raise "You need to specify a tag context using :on" unless opts.has_key?(:on)
- raise "You need to specify some tags using :with" unless opts.has_key?(:with)
- raise "No context :#{opts[:on]} defined in #{taggable.class.to_s}" unless (opts[:force] || taggable.tag_types.include?(opts[:on]))
-
- taggable.set_owner_tag_list_on(self, opts[:on].to_s, opts[:with])
- taggable.save unless skip_save
- end
-
- def is_tagger?
- self.class.is_tagger?
- end
- end
-
- module SingletonMethods
- def is_tagger?
- true
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tagging.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tagging.rb
deleted file mode 100644
index 4bcae5a61..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tagging.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-module ActsAsTaggableOn
- class Tagging < ::ActiveRecord::Base #:nodoc:
- attr_accessible :tag,
- :tag_id,
- :context,
- :taggable,
- :taggable_type,
- :taggable_id,
- :tagger,
- :tagger_type,
- :tagger_id if defined?(ActiveModel::MassAssignmentSecurity)
-
- belongs_to :tag, :class_name => 'ActsAsTaggableOn::Tag'
- belongs_to :taggable, :polymorphic => true
- belongs_to :tagger, :polymorphic => true
-
- validates_presence_of :context
- validates_presence_of :tag_id
-
- validates_uniqueness_of :tag_id, :scope => [ :taggable_type, :taggable_id, :context, :tagger_id, :tagger_type ]
-
- after_destroy :remove_unused_tags
-
- private
-
- def remove_unused_tags
- if ActsAsTaggableOn.remove_unused_tags
- if tag.taggings.count.zero?
- tag.destroy
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tags_helper.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tags_helper.rb
deleted file mode 100644
index 29701ba2f..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/tags_helper.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-module ActsAsTaggableOn
- module TagsHelper
- # See the README for an example using tag_cloud.
- def tag_cloud(tags, classes)
- return [] if tags.empty?
-
- max_count = tags.sort_by(&:count).last.count.to_f
-
- tags.each do |tag|
- index = ((tag.count / max_count) * (classes.size - 1))
- yield tag, classes[index.nan? ? 0 : index.round]
- end
- end
-
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/utils.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/utils.rb
deleted file mode 100644
index 02f7e07b0..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/utils.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-module ActsAsTaggableOn
- module Utils
- def self.included(base)
-
- base.send :include, ActsAsTaggableOn::Utils::OverallMethods
- base.extend ActsAsTaggableOn::Utils::OverallMethods
- end
-
- module OverallMethods
- def using_postgresql?
- ::ActiveRecord::Base.connection && ::ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
- end
-
- def using_sqlite?
- ::ActiveRecord::Base.connection && ::ActiveRecord::Base.connection.adapter_name == 'SQLite'
- end
-
- def sha_prefix(string)
- Digest::SHA1.hexdigest("#{string}#{rand}")[0..6]
- end
-
- private
- def like_operator
- using_postgresql? ? 'ILIKE' : 'LIKE'
- end
-
- # escape _ and % characters in strings, since these are wildcards in SQL.
- def escape_like(str)
- str.gsub(/[!%_]/){ |x| '!' + x }
- end
- end
-
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/version.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/version.rb
deleted file mode 100644
index 16ffef090..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/acts_as_taggable_on/version.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-module ActsAsTaggableOn
- VERSION = '2.4.2.pre'
-end
-
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/generators/acts_as_taggable_on/migration/migration_generator.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/generators/acts_as_taggable_on/migration/migration_generator.rb
deleted file mode 100644
index bb1e69311..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/generators/acts_as_taggable_on/migration/migration_generator.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require 'rails/generators'
-require 'rails/generators/migration'
-
-module ActsAsTaggableOn
- class MigrationGenerator < Rails::Generators::Base
- include Rails::Generators::Migration
-
- desc "Generates migration for Tag and Tagging models"
-
- def self.orm
- Rails::Generators.options[:rails][:orm]
- end
-
- def self.source_root
- File.join(File.dirname(__FILE__), 'templates', (orm.to_s unless orm.class.eql?(String)) )
- end
-
- def self.orm_has_migration?
- [:active_record].include? orm
- end
-
- def self.next_migration_number(dirname)
- if ActiveRecord::Base.timestamped_migrations
- migration_number = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
- migration_number += 1
- migration_number.to_s
- else
- "%.3d" % (current_migration_number(dirname) + 1)
- end
- end
-
- def create_migration_file
- if self.class.orm_has_migration?
- migration_template 'migration.rb', 'db/migrate/acts_as_taggable_on_migration'
- end
- end
- end
-end
-
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb b/trustie2/lib/plugins/acts-as-taggable-on/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb
deleted file mode 100644
index e8b978d96..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/lib/generators/acts_as_taggable_on/migration/templates/active_record/migration.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-class ActsAsTaggableOnMigration < ActiveRecord::Migration
- def self.up
- create_table :tags do |t|
- t.string :name
- end
-
- create_table :taggings do |t|
- t.references :tag
-
- # You should make sure that the column created is
- # long enough to store the required class names.
- t.references :taggable, :polymorphic => true
- t.references :tagger, :polymorphic => true
-
- # Limit is created to prevent MySQL error on index
- # length for MyISAM table type: http://bit.ly/vgW2Ql
- t.string :context, :limit => 128
-
- t.datetime :created_at
- end
-
- add_index :taggings, :tag_id
- add_index :taggings, [:taggable_id, :taggable_type, :context]
- end
-
- def self.down
- drop_table :taggings
- drop_table :tags
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb
deleted file mode 100644
index fa2c6010e..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/acts_as_taggable_on_spec.rb
+++ /dev/null
@@ -1,264 +0,0 @@
-require 'spec_helper'
-
-describe "Acts As Taggable On" do
- before(:each) do
- clean_database!
- end
-
- it "should provide a class method 'taggable?' that is false for untaggable models" do
- UntaggableModel.should_not be_taggable
- end
-
- describe "Taggable Method Generation To Preserve Order" do
- before(:each) do
- clean_database!
- TaggableModel.tag_types = []
- TaggableModel.preserve_tag_order = false
- TaggableModel.acts_as_ordered_taggable_on(:ordered_tags)
- @taggable = TaggableModel.new(:name => "Bob Jones")
- end
-
- it "should respond 'true' to preserve_tag_order?" do
- @taggable.class.preserve_tag_order?.should be_true
- end
- end
-
- describe "Taggable Method Generation" do
- before(:each) do
- clean_database!
- TaggableModel.tag_types = []
- TaggableModel.acts_as_taggable_on(:tags, :languages, :skills, :needs, :offerings)
- @taggable = TaggableModel.new(:name => "Bob Jones")
- end
-
- it "should respond 'true' to taggable?" do
- @taggable.class.should be_taggable
- end
-
- it "should create a class attribute for tag types" do
- @taggable.class.should respond_to(:tag_types)
- end
-
- it "should create an instance attribute for tag types" do
- @taggable.should respond_to(:tag_types)
- end
-
- it "should have all tag types" do
- @taggable.tag_types.should == [:tags, :languages, :skills, :needs, :offerings]
- end
-
- it "should create a class attribute for preserve tag order" do
- @taggable.class.should respond_to(:preserve_tag_order?)
- end
-
- it "should create an instance attribute for preserve tag order" do
- @taggable.should respond_to(:preserve_tag_order?)
- end
-
- it "should respond 'false' to preserve_tag_order?" do
- @taggable.class.preserve_tag_order?.should be_false
- end
-
- it "should generate an association for each tag type" do
- @taggable.should respond_to(:tags, :skills, :languages)
- end
-
- it "should add tagged_with and tag_counts to singleton" do
- TaggableModel.should respond_to(:tagged_with, :tag_counts)
- end
-
- it "should generate a tag_list accessor/setter for each tag type" do
- @taggable.should respond_to(:tag_list, :skill_list, :language_list)
- @taggable.should respond_to(:tag_list=, :skill_list=, :language_list=)
- end
-
- it "should generate a tag_list accessor, that includes owned tags, for each tag type" do
- @taggable.should respond_to(:all_tags_list, :all_skills_list, :all_languages_list)
- end
- end
-
- describe "Reloading" do
- it "should save a model instantiated by Model.find" do
- taggable = TaggableModel.create!(:name => "Taggable")
- found_taggable = TaggableModel.find(taggable.id)
- found_taggable.save
- end
- end
-
- describe "Matching Contexts" do
- it "should find objects with tags of matching contexts" do
- taggable1 = TaggableModel.create!(:name => "Taggable 1")
- taggable2 = TaggableModel.create!(:name => "Taggable 2")
- taggable3 = TaggableModel.create!(:name => "Taggable 3")
-
- taggable1.offering_list = "one, two"
- taggable1.save!
-
- taggable2.need_list = "one, two"
- taggable2.save!
-
- taggable3.offering_list = "one, two"
- taggable3.save!
-
- taggable1.find_matching_contexts(:offerings, :needs).should include(taggable2)
- taggable1.find_matching_contexts(:offerings, :needs).should_not include(taggable3)
- end
-
- it "should find other related objects with tags of matching contexts" do
- taggable1 = TaggableModel.create!(:name => "Taggable 1")
- taggable2 = OtherTaggableModel.create!(:name => "Taggable 2")
- taggable3 = OtherTaggableModel.create!(:name => "Taggable 3")
-
- taggable1.offering_list = "one, two"
- taggable1.save
-
- taggable2.need_list = "one, two"
- taggable2.save
-
- taggable3.offering_list = "one, two"
- taggable3.save
-
- taggable1.find_matching_contexts_for(OtherTaggableModel, :offerings, :needs).should include(taggable2)
- taggable1.find_matching_contexts_for(OtherTaggableModel, :offerings, :needs).should_not include(taggable3)
- end
-
- it "should not include the object itself in the list of related objects with tags of matching contexts" do
- taggable1 = TaggableModel.create!(:name => "Taggable 1")
- taggable2 = TaggableModel.create!(:name => "Taggable 2")
-
- taggable1.offering_list = "one, two"
- taggable1.need_list = "one, two"
- taggable1.save
-
- taggable2.need_list = "one, two"
- taggable2.save
-
- taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(taggable2)
- taggable1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(taggable1)
- end
-
- end
-
- describe 'Tagging Contexts' do
- it 'should eliminate duplicate tagging contexts ' do
- TaggableModel.acts_as_taggable_on(:skills, :skills)
- TaggableModel.tag_types.freq[:skills].should_not == 3
- end
-
- it "should not contain embedded/nested arrays" do
- TaggableModel.acts_as_taggable_on([:array], [:array])
- TaggableModel.tag_types.freq[[:array]].should == 0
- end
-
- it "should _flatten_ the content of arrays" do
- TaggableModel.acts_as_taggable_on([:array], [:array])
- TaggableModel.tag_types.freq[:array].should == 1
- end
-
- it "should not raise an error when passed nil" do
- lambda {
- TaggableModel.acts_as_taggable_on()
- }.should_not raise_error
- end
-
- it "should not raise an error when passed [nil]" do
- lambda {
- TaggableModel.acts_as_taggable_on([nil])
- }.should_not raise_error
- end
- end
-
- context 'when tagging context ends in an "s" when singular (ex. "status", "glass", etc.)' do
- describe 'caching' do
- before { @taggable = OtherCachedModel.new(:name => "John Smith") }
- title { @taggable }
-
- it { should respond_to(:save_cached_tag_list) }
- its(:cached_language_list) { should be_blank }
- its(:cached_status_list) { should be_blank }
- its(:cached_glass_list) { should be_blank }
-
- context 'language taggings cache after update' do
- before { @taggable.update_attributes(:language_list => 'ruby, .net') }
- title { @taggable }
-
- its(:language_list) { should == ['ruby', '.net']}
- its(:cached_language_list) { should == 'ruby, .net' } # passes
- its(:instance_variables) { should include((RUBY_VERSION < '1.9' ? '@language_list' : :@language_list)) }
- end
-
- context 'status taggings cache after update' do
- before { @taggable.update_attributes(:status_list => 'happy, married') }
- title { @taggable }
-
- its(:status_list) { should == ['happy', 'married'] }
- its(:cached_status_list) { should == 'happy, married' } # fails
- its(:cached_status_list) { should_not == '' } # fails, is blank
- its(:instance_variables) { should include((RUBY_VERSION < '1.9' ? '@status_list' : :@status_list)) }
- its(:instance_variables) { should_not include((RUBY_VERSION < '1.9' ? '@statu_list' : :@statu_list)) } # fails, note: one "s"
-
- end
-
- context 'glass taggings cache after update' do
- before do
- @taggable.update_attributes(:glass_list => 'rectangle, aviator')
- end
-
- title { @taggable }
- its(:glass_list) { should == ['rectangle', 'aviator'] }
- its(:cached_glass_list) { should == 'rectangle, aviator' } # fails
- its(:cached_glass_list) { should_not == '' } # fails, is blank
- if RUBY_VERSION < '1.9'
- its(:instance_variables) { should include('@glass_list') }
- its(:instance_variables) { should_not include('@glas_list') } # fails, note: one "s"
- else
- its(:instance_variables) { should include(:@glass_list) }
- its(:instance_variables) { should_not include(:@glas_list) } # fails, note: one "s"
- end
-
- end
- end
- end
-
- describe "taggings" do
- before(:each) do
- @taggable = TaggableModel.new(:name => "Art Kram")
- end
-
- it 'should return [] taggings' do
- @taggable.taggings.should == []
- end
- end
-
- describe "@@remove_unused_tags" do
- before do
- @taggable = TaggableModel.create(:name => "Bob Jones")
- @tag = ActsAsTaggableOn::Tag.create(:name => "awesome")
-
- @tagging = ActsAsTaggableOn::Tagging.create(:taggable => @taggable, :tag => @tag, :context => 'tags')
- end
-
- context "if set to true" do
- before do
- ActsAsTaggableOn.remove_unused_tags = true
- end
-
- it "should remove unused tags after removing taggings" do
- @tagging.destroy
- ActsAsTaggableOn::Tag.find_by_name("awesome").should be_nil
- end
- end
-
- context "if set to false" do
- before do
- ActsAsTaggableOn.remove_unused_tags = false
- end
-
- it "should not remove unused tags after removing taggings" do
- @tagging.destroy
- ActsAsTaggableOn::Tag.find_by_name("awesome").should == @tag
- end
- end
- end
-
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/acts_as_tagger_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/acts_as_tagger_spec.rb
deleted file mode 100644
index 9591fcba3..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/acts_as_tagger_spec.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-require 'spec_helper'
-
-describe "acts_as_tagger" do
- before(:each) do
- clean_database!
- end
-
- describe "Tagger Method Generation" do
- before(:each) do
- @tagger = User.new
- end
-
- it "should add #is_tagger? query method to the class-side" do
- User.should respond_to(:is_tagger?)
- end
-
- it "should return true from the class-side #is_tagger?" do
- User.is_tagger?.should be_true
- end
-
- it "should return false from the base #is_tagger?" do
- ActiveRecord::Base.is_tagger?.should be_false
- end
-
- it "should add #is_tagger? query method to the singleton" do
- @tagger.should respond_to(:is_tagger?)
- end
-
- it "should add #tag method on the instance-side" do
- @tagger.should respond_to(:tag)
- end
-
- it "should generate an association for #owned_taggings and #owned_tags" do
- @tagger.should respond_to(:owned_taggings, :owned_tags)
- end
- end
-
- describe "#tag" do
- context 'when called with a non-existent tag context' do
- before(:each) do
- @tagger = User.new
- @taggable = TaggableModel.new(:name=>"Richard Prior")
- end
-
- it "should by default not throw an exception " do
- @taggable.tag_list_on(:foo).should be_empty
- lambda {
- @tagger.tag(@taggable, :with=>'this, and, that', :on=>:foo)
- }.should_not raise_error
- end
-
- it 'should by default create the tag context on-the-fly' do
- @taggable.tag_list_on(:here_ond_now).should be_empty
- @tagger.tag(@taggable, :with=>'that', :on => :here_ond_now)
- @taggable.tag_list_on(:here_ond_now).should_not include('that')
- @taggable.all_tags_list_on(:here_ond_now).should include('that')
- end
-
- it "should show all the tag list when both public and owned tags exist" do
- @taggable.tag_list = 'ruby, python'
- @tagger.tag(@taggable, :with => 'java, lisp', :on => :tags)
- @taggable.all_tags_on(:tags).map(&:name).sort.should == %w(ruby python java lisp).sort
- end
-
- it "should not add owned tags to the common list" do
- @taggable.tag_list = 'ruby, python'
- @tagger.tag(@taggable, :with => 'java, lisp', :on => :tags)
- @taggable.tag_list.should == %w(ruby python)
- @tagger.tag(@taggable, :with => '', :on => :tags)
- @taggable.tag_list.should == %w(ruby python)
- end
-
- it "should throw an exception when the default is over-ridden" do
- @taggable.tag_list_on(:foo_boo).should be_empty
- lambda {
- @tagger.tag(@taggable, :with=>'this, and, that', :on=>:foo_boo, :force=>false)
- }.should raise_error
- end
-
- it "should not create the tag context on-the-fly when the default is over-ridden" do
- @taggable.tag_list_on(:foo_boo).should be_empty
- @tagger.tag(@taggable, :with=>'this, and, that', :on=>:foo_boo, :force=>false) rescue
- @taggable.tag_list_on(:foo_boo).should be_empty
- end
- end
-
- describe "when called by multiple tagger's" do
- before(:each) do
- @user_x = User.create(:name => "User X")
- @user_y = User.create(:name => "User Y")
- @taggable = TaggableModel.create(:name => 'acts_as_taggable_on', :tag_list => 'plugin')
-
- @user_x.tag(@taggable, :with => 'ruby, rails', :on => :tags)
- @user_y.tag(@taggable, :with => 'ruby, plugin', :on => :tags)
-
- @user_y.tag(@taggable, :with => '', :on => :tags)
- @user_y.tag(@taggable, :with => '', :on => :tags)
- end
-
- it "should delete owned tags" do
- @user_y.owned_tags.should == []
- end
-
- it "should not delete other taggers tags" do
- @user_x.owned_tags.should have(2).items
- end
-
- it "should not delete original tags" do
- @taggable.all_tags_list_on(:tags).should include('plugin')
- end
- end
- end
-
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/caching_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/caching_spec.rb
deleted file mode 100644
index 5aab999d9..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/caching_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'spec_helper'
-
-describe "Acts As Taggable On" do
-
- before(:each) do
- clean_database!
- end
-
- describe 'Caching' do
- before(:each) do
- @taggable = CachedModel.new(:name => "Bob Jones")
- @another_taggable = OtherCachedModel.new(:name => "John Smith")
- end
-
- it "should add saving of tag lists and cached tag lists to the instance" do
- @taggable.should respond_to(:save_cached_tag_list)
- @another_taggable.should respond_to(:save_cached_tag_list)
-
- @taggable.should respond_to(:save_tags)
- end
-
- it "should add cached tag lists to the instance if cached column is not present" do
- TaggableModel.new(:name => "Art Kram").should_not respond_to(:save_cached_tag_list)
- end
-
- it "should generate a cached column checker for each tag type" do
- CachedModel.should respond_to(:caching_tag_list?)
- OtherCachedModel.should respond_to(:caching_language_list?)
- end
-
- it 'should not have cached tags' do
- @taggable.cached_tag_list.should be_blank
- @another_taggable.cached_language_list.should be_blank
- end
-
- it 'should cache tags' do
- @taggable.update_attributes(:tag_list => 'awesome, epic')
- @taggable.cached_tag_list.should == 'awesome, epic'
-
- @another_taggable.update_attributes(:language_list => 'ruby, .net')
- @another_taggable.cached_language_list.should == 'ruby, .net'
- end
-
- it 'should keep the cache' do
- @taggable.update_attributes(:tag_list => 'awesome, epic')
- @taggable = CachedModel.find(@taggable)
- @taggable.save!
- @taggable.cached_tag_list.should == 'awesome, epic'
- end
-
- it 'should update the cache' do
- @taggable.update_attributes(:tag_list => 'awesome, epic')
- @taggable.update_attributes(:tag_list => 'awesome')
- @taggable.cached_tag_list.should == 'awesome'
- end
-
- it 'should remove the cache' do
- @taggable.update_attributes(:tag_list => 'awesome, epic')
- @taggable.update_attributes(:tag_list => '')
- @taggable.cached_tag_list.should be_blank
- end
-
- it 'should have a tag list' do
- @taggable.update_attributes(:tag_list => 'awesome, epic')
- @taggable = CachedModel.find(@taggable.id)
- @taggable.tag_list.sort.should == %w(awesome epic).sort
- end
-
- it 'should keep the tag list' do
- @taggable.update_attributes(:tag_list => 'awesome, epic')
- @taggable = CachedModel.find(@taggable.id)
- @taggable.save!
- @taggable.tag_list.sort.should == %w(awesome epic).sort
- end
- end
-
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/related_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/related_spec.rb
deleted file mode 100644
index acbc8fd5e..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/related_spec.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-require 'spec_helper'
-
-describe "Acts As Taggable On" do
- before(:each) do
- clean_database!
- end
-
- describe "Related Objects" do
- it "should find related objects based on tag names on context" do
- taggable1 = TaggableModel.create!(:name => "Taggable 1")
- taggable2 = TaggableModel.create!(:name => "Taggable 2")
- taggable3 = TaggableModel.create!(:name => "Taggable 3")
-
- taggable1.tag_list = "one, two"
- taggable1.save
-
- taggable2.tag_list = "three, four"
- taggable2.save
-
- taggable3.tag_list = "one, four"
- taggable3.save
-
- taggable1.find_related_tags.should include(taggable3)
- taggable1.find_related_tags.should_not include(taggable2)
- end
-
- it "finds related tags for ordered taggable on" do
- taggable1 = OrderedTaggableModel.create!(:name => "Taggable 1")
- taggable2 = OrderedTaggableModel.create!(:name => "Taggable 2")
- taggable3 = OrderedTaggableModel.create!(:name => "Taggable 3")
-
- taggable1.colour_list = "one, two"
- taggable1.save
-
- taggable2.colour_list = "three, four"
- taggable2.save
-
- taggable3.colour_list = "one, four"
- taggable3.save
-
- taggable1.find_related_colours.should include(taggable3)
- taggable1.find_related_colours.should_not include(taggable2)
- end
-
- it "should find related objects based on tag names on context - non standard id" do
- taggable1 = NonStandardIdTaggableModel.create!(:name => "Taggable 1")
- taggable2 = NonStandardIdTaggableModel.create!(:name => "Taggable 2")
- taggable3 = NonStandardIdTaggableModel.create!(:name => "Taggable 3")
-
- taggable1.tag_list = "one, two"
- taggable1.save
-
- taggable2.tag_list = "three, four"
- taggable2.save
-
- taggable3.tag_list = "one, four"
- taggable3.save
-
- taggable1.find_related_tags.should include(taggable3)
- taggable1.find_related_tags.should_not include(taggable2)
- end
-
- it "should find other related objects based on tag names on context" do
- taggable1 = TaggableModel.create!(:name => "Taggable 1")
- taggable2 = OtherTaggableModel.create!(:name => "Taggable 2")
- taggable3 = OtherTaggableModel.create!(:name => "Taggable 3")
-
- taggable1.tag_list = "one, two"
- taggable1.save
-
- taggable2.tag_list = "three, four"
- taggable2.save
-
- taggable3.tag_list = "one, four"
- taggable3.save
-
- taggable1.find_related_tags_for(OtherTaggableModel).should include(taggable3)
- taggable1.find_related_tags_for(OtherTaggableModel).should_not include(taggable2)
- end
-
- it "should not include the object itself in the list of related objects" do
- taggable1 = TaggableModel.create!(:name => "Taggable 1")
- taggable2 = TaggableModel.create!(:name => "Taggable 2")
-
- taggable1.tag_list = "one"
- taggable1.save
-
- taggable2.tag_list = "one, two"
- taggable2.save
-
- taggable1.find_related_tags.should include(taggable2)
- taggable1.find_related_tags.should_not include(taggable1)
- end
-
- it "should not include the object itself in the list of related objects - non standard id" do
- taggable1 = NonStandardIdTaggableModel.create!(:name => "Taggable 1")
- taggable2 = NonStandardIdTaggableModel.create!(:name => "Taggable 2")
-
- taggable1.tag_list = "one"
- taggable1.save
-
- taggable2.tag_list = "one, two"
- taggable2.save
-
- taggable1.find_related_tags.should include(taggable2)
- taggable1.find_related_tags.should_not include(taggable1)
- end
-
- context "Ignored Tags" do
- let(:taggable1) { TaggableModel.create!(:name => "Taggable 1") }
- let(:taggable2) { TaggableModel.create!(:name => "Taggable 2") }
- let(:taggable3) { TaggableModel.create!(:name => "Taggable 3") }
- before(:each) do
- taggable1.tag_list = "one, two, four"
- taggable1.save
-
- taggable2.tag_list = "two, three"
- taggable2.save
-
- taggable3.tag_list = "one, three"
- taggable3.save
- end
- it "should not include ignored tags in related search" do
- taggable1.find_related_tags(:ignore => 'two').should_not include(taggable2)
- taggable1.find_related_tags(:ignore => 'two').should include(taggable3)
- end
-
- it "should accept array of ignored tags" do
- taggable4 = TaggableModel.create!(:name => "Taggable 4")
- taggable4.tag_list = "four"
- taggable4.save
-
- taggable1.find_related_tags(:ignore => ['two', 'four']).should_not include(taggable2)
- taggable1.find_related_tags(:ignore => ['two', 'four']).should_not include(taggable4)
- end
-
- it "should accept symbols as ignored tags" do
- taggable1.find_related_tags(:ignore => :two).should_not include(taggable2)
- end
- end
-
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/single_table_inheritance_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/single_table_inheritance_spec.rb
deleted file mode 100644
index 4d8ca57b8..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/single_table_inheritance_spec.rb
+++ /dev/null
@@ -1,187 +0,0 @@
-require 'spec_helper'
-
-describe "Single Table Inheritance" do
-
- before(:each) do
- clean_database!
- end
-
- let(:taggable) { TaggableModel.new(:name => "taggable model") }
-
- let(:inheriting_model) { InheritingTaggableModel.new(:name => "Inheriting Taggable Model") }
- let(:altered_inheriting) { AlteredInheritingTaggableModel.new(:name => "Altered Inheriting Model") }
-
- 1.upto(4) do |n|
- let(:"inheriting_#{n}") { InheritingTaggableModel.new(:name => "Inheriting Model #{n}") }
- end
-
- let(:student) { Student.create! }
-
- describe "tag contexts" do
- it "should pass on to STI-inherited models" do
- inheriting_model.should respond_to(:tag_list, :skill_list, :language_list)
- altered_inheriting.should respond_to(:tag_list, :skill_list, :language_list)
- end
-
- it "should pass on to altered STI models" do
- altered_inheriting.should respond_to(:part_list)
- end
- end
-
- context "matching contexts" do
-
- before do
- inheriting_1.offering_list = "one, two"
- inheriting_1.need_list = "one, two"
- inheriting_1.save!
-
- inheriting_2.need_list = "one, two"
- inheriting_2.save!
-
- inheriting_3.offering_list = "one, two"
- inheriting_3.save!
-
- inheriting_4.tag_list = "one, two, three, four"
- inheriting_4.save!
-
- taggable.need_list = "one, two"
- taggable.save!
- end
-
- it "should find objects with tags of matching contexts" do
- inheriting_1.find_matching_contexts(:offerings, :needs).should include(inheriting_2)
- inheriting_1.find_matching_contexts(:offerings, :needs).should_not include(inheriting_3)
- inheriting_1.find_matching_contexts(:offerings, :needs).should_not include(inheriting_4)
- inheriting_1.find_matching_contexts(:offerings, :needs).should_not include(taggable)
-
- inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(inheriting_2)
- inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(inheriting_3)
- inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(inheriting_4)
- inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should include(taggable)
- end
-
- it "should not include the object itself in the list of related objects with tags of matching contexts" do
- inheriting_1.find_matching_contexts(:offerings, :needs).should_not include(inheriting_1)
- inheriting_1.find_matching_contexts_for(InheritingTaggableModel, :offerings, :needs).should_not include(inheriting_1)
- inheriting_1.find_matching_contexts_for(TaggableModel, :offerings, :needs).should_not include(inheriting_1)
- end
- end
-
- context "find related tags" do
- before do
- inheriting_1.tag_list = "one, two"
- inheriting_1.save
-
- inheriting_2.tag_list = "three, four"
- inheriting_2.save
-
- inheriting_3.tag_list = "one, four"
- inheriting_3.save
-
- taggable.tag_list = "one, two, three, four"
- taggable.save
- end
-
- it "should find related objects based on tag names on context" do
- inheriting_1.find_related_tags.should include(inheriting_3)
- inheriting_1.find_related_tags.should_not include(inheriting_2)
- inheriting_1.find_related_tags.should_not include(taggable)
-
- inheriting_1.find_related_tags_for(TaggableModel).should include(inheriting_3)
- inheriting_1.find_related_tags_for(TaggableModel).should_not include(inheriting_2)
- inheriting_1.find_related_tags_for(TaggableModel).should include(taggable)
- end
-
- it "should not include the object itself in the list of related objects" do
- inheriting_1.find_related_tags.should_not include(inheriting_1)
- inheriting_1.find_related_tags_for(InheritingTaggableModel).should_not include(inheriting_1)
- inheriting_1.find_related_tags_for(TaggableModel).should_not include(inheriting_1)
- end
- end
-
- describe "tag list" do
- before do
- @inherited_same = InheritingTaggableModel.new(:name => "inherited same")
- @inherited_different = AlteredInheritingTaggableModel.new(:name => "inherited different")
- end
-
- it "should be able to save tags for inherited models" do
- inheriting_model.tag_list = "bob, kelso"
- inheriting_model.save
- InheritingTaggableModel.tagged_with("bob").first.should == inheriting_model
- end
-
- it "should find STI tagged models on the superclass" do
- inheriting_model.tag_list = "bob, kelso"
- inheriting_model.save
- TaggableModel.tagged_with("bob").first.should == inheriting_model
- end
-
- it "should be able to add on contexts only to some subclasses" do
- altered_inheriting.part_list = "fork, spoon"
- altered_inheriting.save
- InheritingTaggableModel.tagged_with("fork", :on => :parts).should be_empty
- AlteredInheritingTaggableModel.tagged_with("fork", :on => :parts).first.should == altered_inheriting
- end
-
- it "should have different tag_counts_on for inherited models" do
- inheriting_model.tag_list = "bob, kelso"
- inheriting_model.save!
- altered_inheriting.tag_list = "fork, spoon"
- altered_inheriting.save!
-
- InheritingTaggableModel.tag_counts_on(:tags, :order => 'tags.id').map(&:name).should == %w(bob kelso)
- AlteredInheritingTaggableModel.tag_counts_on(:tags, :order => 'tags.id').map(&:name).should == %w(fork spoon)
- TaggableModel.tag_counts_on(:tags, :order => 'tags.id').map(&:name).should == %w(bob kelso fork spoon)
- end
-
- it "should have different tags_on for inherited models" do
- inheriting_model.tag_list = "bob, kelso"
- inheriting_model.save!
- altered_inheriting.tag_list = "fork, spoon"
- altered_inheriting.save!
-
- InheritingTaggableModel.tags_on(:tags, :order => 'tags.id').map(&:name).should == %w(bob kelso)
- AlteredInheritingTaggableModel.tags_on(:tags, :order => 'tags.id').map(&:name).should == %w(fork spoon)
- TaggableModel.tags_on(:tags, :order => 'tags.id').map(&:name).should == %w(bob kelso fork spoon)
- end
-
- it 'should store same tag without validation conflict' do
- taggable.tag_list = 'one'
- taggable.save!
-
- inheriting_model.tag_list = 'one'
- inheriting_model.save!
-
- inheriting_model.update_attributes! :name => 'foo'
- end
- end
-
- describe "ownership" do
- it "should have taggings" do
- student.tag(taggable, :with=>'ruby,scheme', :on=>:tags)
- student.owned_taggings.should have(2).tags
- end
-
- it "should have tags" do
- student.tag(taggable, :with=>'ruby,scheme', :on=>:tags)
- student.owned_tags.should have(2).tags
- end
-
- it "should return tags for the inheriting tagger" do
- student.tag(taggable, :with => 'ruby, scheme', :on => :tags)
- taggable.tags_from(student).should match_array(%w(ruby scheme))
- end
-
- it "returns owner tags on the tagger" do
- student.tag(taggable, :with => 'ruby, scheme', :on => :tags)
- taggable.owner_tags_on(student, :tags).should have(2).tags
- end
-
- it "should scope objects returned by tagged_with by owners" do
- student.tag(taggable, :with => 'ruby, scheme', :on => :tags)
- TaggableModel.tagged_with(%w(ruby scheme), :owned_by => student).should have(1).tag
- end
- end
-
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tag_list_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tag_list_spec.rb
deleted file mode 100644
index cb8afb312..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tag_list_spec.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# encoding: utf-8
-require 'spec_helper'
-
-describe ActsAsTaggableOn::TagList do
- let(:tag_list) { ActsAsTaggableOn::TagList.new("awesome","radical") }
-
- it { should be_kind_of Array }
-
- it "#from should return empty array if empty array is passed" do
- ActsAsTaggableOn::TagList.from([]).should be_empty
- end
-
- describe "#add" do
- it "should be able to be add a new tag word" do
- tag_list.add("cool")
- tag_list.include?("cool").should be_true
- end
-
- it "should be able to add delimited lists of words" do
- tag_list.add("cool, wicked", :parse => true)
- tag_list.should include("cool", "wicked")
- end
-
- it "should be able to add delimited list of words with quoted delimiters" do
- tag_list.add("'cool, wicked', \"really cool, really wicked\"", :parse => true)
- tag_list.should include("cool, wicked", "really cool, really wicked")
- end
-
- it "should be able to handle other uses of quotation marks correctly" do
- tag_list.add("john's cool car, mary's wicked toy", :parse => true)
- tag_list.should include("john's cool car", "mary's wicked toy")
- end
-
- it "should be able to add an array of words" do
- tag_list.add(["cool", "wicked"], :parse => true)
- tag_list.should include("cool", "wicked")
- end
-
- it "should quote escape tags with commas in them" do
- tag_list.add("cool","rad,bodacious")
- tag_list.to_s.should == "awesome, radical, cool, \"rad,bodacious\""
- end
-
- end
-
- describe "#remove" do
- it "should be able to remove words" do
- tag_list.remove("awesome")
- tag_list.should_not include("awesome")
- end
-
- it "should be able to remove delimited lists of words" do
- tag_list.remove("awesome, radical", :parse => true)
- tag_list.should be_empty
- end
-
- it "should be able to remove an array of words" do
- tag_list.remove(["awesome", "radical"], :parse => true)
- tag_list.should be_empty
- end
- end
-
- describe "#to_s" do
- it "should give a delimited list of words when converted to string" do
- tag_list.to_s.should == "awesome, radical"
- end
-
- it "should be able to call to_s on a frozen tag list" do
- tag_list.freeze
- lambda { tag_list.add("cool","rad,bodacious") }.should raise_error
- lambda { tag_list.to_s }.should_not raise_error
- end
- end
-
- describe "cleaning" do
- it "should parameterize if force_parameterize is set to true" do
- ActsAsTaggableOn.force_parameterize = true
- tag_list = ActsAsTaggableOn::TagList.new("awesome()","radical)(cc")
-
- tag_list.to_s.should == "awesome, radical-cc"
- ActsAsTaggableOn.force_parameterize = false
- end
-
- it "should lowercase if force_lowercase is set to true" do
- ActsAsTaggableOn.force_lowercase = true
-
- tag_list = ActsAsTaggableOn::TagList.new("aweSomE","RaDicaL","Entrée")
- tag_list.to_s.should == "awesome, radical, entrée"
-
- ActsAsTaggableOn.force_lowercase = false
- end
-
- end
-
- describe "Multiple Delimiter" do
- before do
- @old_delimiter = ActsAsTaggableOn.delimiter
- end
-
- after do
- ActsAsTaggableOn.delimiter = @old_delimiter
- end
-
- it "should separate tags by delimiters" do
- ActsAsTaggableOn.delimiter = [',', ' ', '\|']
- tag_list = ActsAsTaggableOn::TagList.from "cool, data|I have"
- tag_list.to_s.should == 'cool, data, I, have'
- end
-
- it "should escape quote" do
- ActsAsTaggableOn.delimiter = [',', ' ', '\|']
- tag_list = ActsAsTaggableOn::TagList.from "'I have'|cool, data"
- tag_list.to_s.should == '"I have", cool, data'
-
- tag_list = ActsAsTaggableOn::TagList.from '"I, have"|cool, data'
- tag_list.to_s.should == '"I, have", cool, data'
- end
-
- it "should work for utf8 delimiter and long delimiter" do
- ActsAsTaggableOn.delimiter = [',', '的', '可能是']
- tag_list = ActsAsTaggableOn::TagList.from "我的东西可能是不见了,还好有备份"
- tag_list.to_s.should == "我, 东西, 不见了, 还好有备份"
- end
- end
-
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tag_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tag_spec.rb
deleted file mode 100644
index 74c9d4550..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tag_spec.rb
+++ /dev/null
@@ -1,211 +0,0 @@
-# encoding: utf-8
-require 'spec_helper'
-
-describe ActsAsTaggableOn::Tag do
- before(:each) do
- clean_database!
- @tag = ActsAsTaggableOn::Tag.new
- @user = TaggableModel.create(:name => "Pablo")
- end
-
- describe "named like any" do
- before(:each) do
- ActsAsTaggableOn::Tag.create(:name => "Awesome")
- ActsAsTaggableOn::Tag.create(:name => "awesome")
- ActsAsTaggableOn::Tag.create(:name => "epic")
- end
-
- it "should find both tags" do
- ActsAsTaggableOn::Tag.named_like_any(["awesome", "epic"]).should have(3).items
- end
- end
-
- describe "find or create by name" do
- before(:each) do
- @tag.name = "awesome"
- @tag.save
- end
-
- it "should find by name" do
- ActsAsTaggableOn::Tag.find_or_create_with_like_by_name("awesome").should == @tag
- end
-
- it "should find by name case insensitive" do
- ActsAsTaggableOn::Tag.find_or_create_with_like_by_name("AWESOME").should == @tag
- end
-
- it "should create by name" do
- lambda {
- ActsAsTaggableOn::Tag.find_or_create_with_like_by_name("epic")
- }.should change(ActsAsTaggableOn::Tag, :count).by(1)
- end
- end
-
- unless ActsAsTaggableOn::Tag.using_sqlite?
- describe "find or create by unicode name" do
- before(:each) do
- @tag.name = "привет"
- @tag.save
- end
-
- it "should find by name" do
- ActsAsTaggableOn::Tag.find_or_create_with_like_by_name("привет").should == @tag
- end
-
- it "should find by name case insensitive" do
- ActsAsTaggableOn::Tag.find_or_create_with_like_by_name("ПРИВЕТ").should == @tag
- end
- end
- end
-
- describe "find or create all by any name" do
- before(:each) do
- @tag.name = "awesome"
- @tag.save
- end
-
- it "should find by name" do
- ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name("awesome").should == [@tag]
- end
-
- it "should find by name case insensitive" do
- ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name("AWESOME").should == [@tag]
- end
-
- it "should create by name" do
- lambda {
- ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name("epic")
- }.should change(ActsAsTaggableOn::Tag, :count).by(1)
- end
-
- it "should find or create by name" do
- lambda {
- ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name("awesome", "epic").map(&:name).should == ["awesome", "epic"]
- }.should change(ActsAsTaggableOn::Tag, :count).by(1)
- end
-
- it "should return an empty array if no tags are specified" do
- ActsAsTaggableOn::Tag.find_or_create_all_with_like_by_name([]).should == []
- end
- end
-
- it "should require a name" do
- @tag.valid?
-
- @tag.errors[:name].should == ["can't be blank"]
-
- @tag.name = "something"
- @tag.valid?
-
- @tag.errors[:name].should == []
- end
-
- it "should limit the name length to 255 or less characters" do
- @tag.name = "fgkgnkkgjymkypbuozmwwghblmzpqfsgjasflblywhgkwndnkzeifalfcpeaeqychjuuowlacmuidnnrkprgpcpybarbkrmziqihcrxirlokhnzfvmtzixgvhlxzncyywficpraxfnjptxxhkqmvicbcdcynkjvziefqzyndxkjmsjlvyvbwraklbalykyxoliqdlreeykuphdtmzfdwpphmrqvwvqffojkqhlzvinqajsxbszyvrqqyzusxranr"
- @tag.valid?
- @tag.errors[:name].should == ["is too long (maximum is 255 characters)"]
-
- @tag.name = "fgkgnkkgjymkypbuozmwwghblmzpqfsgjasflblywhgkwndnkzeifalfcpeaeqychjuuowlacmuidnnrkprgpcpybarbkrmziqihcrxirlokhnzfvmtzixgvhlxzncyywficpraxfnjptxxhkqmvicbcdcynkjvziefqzyndxkjmsjlvyvbwraklbalykyxoliqdlreeykuphdtmzfdwpphmrqvwvqffojkqhlzvinqajsxbszyvrqqyzusxran"
- @tag.valid?
- @tag.errors[:name].should == []
- end
-
- it "should equal a tag with the same name" do
- @tag.name = "awesome"
- new_tag = ActsAsTaggableOn::Tag.new(:name => "awesome")
- new_tag.should == @tag
- end
-
- it "should return its name when to_s is called" do
- @tag.name = "cool"
- @tag.to_s.should == "cool"
- end
-
- it "have named_scope named(something)" do
- @tag.name = "cool"
- @tag.save!
- ActsAsTaggableOn::Tag.named('cool').should include(@tag)
- end
-
- it "have named_scope named_like(something)" do
- @tag.name = "cool"
- @tag.save!
- @another_tag = ActsAsTaggableOn::Tag.create!(:name => "coolip")
- ActsAsTaggableOn::Tag.named_like('cool').should include(@tag, @another_tag)
- end
-
- describe "escape wildcard symbols in like requests" do
- before(:each) do
- @tag.name = "cool"
- @tag.save
- @another_tag = ActsAsTaggableOn::Tag.create!(:name => "coo%")
- @another_tag2 = ActsAsTaggableOn::Tag.create!(:name => "coolish")
- end
-
- it "return escaped result when '%' char present in tag" do
- ActsAsTaggableOn::Tag.named_like('coo%').should_not include(@tag)
- ActsAsTaggableOn::Tag.named_like('coo%').should include(@another_tag)
- end
-
- end
-
- describe "when using strict_case_match" do
- before do
- ActsAsTaggableOn.strict_case_match = true
- @tag.name = "awesome"
- @tag.save!
- end
-
- after do
- ActsAsTaggableOn.strict_case_match = false
- end
-
- it "should find by name" do
- ActsAsTaggableOn::Tag.find_or_create_with_like_by_name("awesome").should == @tag
- end
-
- it "should find by name case sensitively" do
- expect {
- ActsAsTaggableOn::Tag.find_or_create_with_like_by_name("AWESOME")
- }.to change(ActsAsTaggableOn::Tag, :count)
-
- ActsAsTaggableOn::Tag.last.name.should == "AWESOME"
- end
-
- it "should have a named_scope named(something) that matches exactly" do
- uppercase_tag = ActsAsTaggableOn::Tag.create(:name => "Cool")
- @tag.name = "cool"
- @tag.save!
-
- ActsAsTaggableOn::Tag.named('cool').should include(@tag)
- ActsAsTaggableOn::Tag.named('cool').should_not include(uppercase_tag)
- end
- end
-
- describe "name uniqeness validation" do
- let(:duplicate_tag) { ActsAsTaggableOn::Tag.new(:name => 'ror') }
-
- before { ActsAsTaggableOn::Tag.create(:name => 'ror') }
-
- context "when don't need unique names" do
- it "should not run uniqueness validation" do
- duplicate_tag.stub(:validates_name_uniqueness?).and_return(false)
- duplicate_tag.save
- duplicate_tag.should be_persisted
- end
- end
-
- context "when do need unique names" do
- it "should run uniqueness validation" do
- duplicate_tag.should_not be_valid
- end
-
- it "add error to name" do
- duplicate_tag.save
-
- duplicate_tag.should have(1).errors
- duplicate_tag.errors.messages[:name].should include('has already been taken')
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/taggable_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/taggable_spec.rb
deleted file mode 100644
index bb919df6a..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/taggable_spec.rb
+++ /dev/null
@@ -1,623 +0,0 @@
-require 'spec_helper'
-
-describe "Taggable To Preserve Order" do
- before(:each) do
- clean_database!
- @taggable = OrderedTaggableModel.new(:name => "Bob Jones")
- end
-
- it "should have tag types" do
- [:tags, :colours].each do |type|
- OrderedTaggableModel.tag_types.should include type
- end
-
- @taggable.tag_types.should == OrderedTaggableModel.tag_types
- end
-
- it "should have tag associations" do
- [:tags, :colours].each do |type|
- @taggable.respond_to?(type).should be_true
- @taggable.respond_to?("#{type.to_s.singularize}_taggings").should be_true
- end
- end
-
- # it "should have tag associations ordered by id" do
- # [:tags, :colours].each do |type|
- # OrderedTaggableModel.reflect_on_association(type).options[:order].should include('id')
- # OrderedTaggableModel.reflect_on_association("#{type.to_s.singularize}_taggings".to_sym).options[:order].should include('id')
- # end
- # end
-
- it "should have tag methods" do
- [:tags, :colours].each do |type|
- @taggable.respond_to?("#{type.to_s.singularize}_list").should be_true
- @taggable.respond_to?("#{type.to_s.singularize}_list=").should be_true
- @taggable.respond_to?("all_#{type.to_s}_list").should be_true
- end
- end
-
- it "should return tag list in the order the tags were created" do
- # create
- @taggable.tag_list = "rails, ruby, css"
- @taggable.instance_variable_get("@tag_list").instance_of?(ActsAsTaggableOn::TagList).should be_true
-
- lambda {
- @taggable.save
- }.should change(ActsAsTaggableOn::Tag, :count).by(3)
-
- @taggable.reload
- @taggable.tag_list.should == %w(rails ruby css)
-
- # update
- @taggable.tag_list = "pow, ruby, rails"
- @taggable.save
-
- @taggable.reload
- @taggable.tag_list.should == %w(pow ruby rails)
-
- # update with no change
- @taggable.tag_list = "pow, ruby, rails"
- @taggable.save
-
- @taggable.reload
- @taggable.tag_list.should == %w(pow ruby rails)
-
- # update to clear tags
- @taggable.tag_list = ""
- @taggable.save
-
- @taggable.reload
- @taggable.tag_list.should == []
- end
-
- it "should return tag objects in the order the tags were created" do
- # create
- @taggable.tag_list = "pow, ruby, rails"
- @taggable.instance_variable_get("@tag_list").instance_of?(ActsAsTaggableOn::TagList).should be_true
-
- lambda {
- @taggable.save
- }.should change(ActsAsTaggableOn::Tag, :count).by(3)
-
- @taggable.reload
- @taggable.tags.map{|t| t.name}.should == %w(pow ruby rails)
-
- # update
- @taggable.tag_list = "rails, ruby, css, pow"
- @taggable.save
-
- @taggable.reload
- @taggable.tags.map{|t| t.name}.should == %w(rails ruby css pow)
- end
-
- it "should return tag objects in tagging id order" do
- # create
- @taggable.tag_list = "pow, ruby, rails"
- @taggable.save
-
- @taggable.reload
- ids = @taggable.tags.map{|t| t.taggings.first.id}
- ids.should == ids.sort
-
- # update
- @taggable.tag_list = "rails, ruby, css, pow"
- @taggable.save
-
- @taggable.reload
- ids = @taggable.tags.map{|t| t.taggings.first.id}
- ids.should == ids.sort
- end
-end
-
-describe "Taggable" do
- before(:each) do
- clean_database!
- @taggable = TaggableModel.new(:name => "Bob Jones")
- @taggables = [@taggable, TaggableModel.new(:name => "John Doe")]
- end
-
- it "should have tag types" do
- [:tags, :languages, :skills, :needs, :offerings].each do |type|
- TaggableModel.tag_types.should include type
- end
-
- @taggable.tag_types.should == TaggableModel.tag_types
- end
-
- it "should have tag_counts_on" do
- TaggableModel.tag_counts_on(:tags).should be_empty
-
- @taggable.tag_list = ["awesome", "epic"]
- @taggable.save
-
- TaggableModel.tag_counts_on(:tags).length.should == 2
- @taggable.tag_counts_on(:tags).length.should == 2
- end
-
- it "should have tags_on" do
- TaggableModel.tags_on(:tags).should be_empty
-
- @taggable.tag_list = ["awesome", "epic"]
- @taggable.save
-
- TaggableModel.tags_on(:tags).length.should == 2
- @taggable.tags_on(:tags).length.should == 2
- end
-
- it "should return [] right after create" do
- blank_taggable = TaggableModel.new(:name => "Bob Jones")
- blank_taggable.tag_list.should == []
- end
-
- it "should be able to create tags" do
- @taggable.skill_list = "ruby, rails, css"
- @taggable.instance_variable_get("@skill_list").instance_of?(ActsAsTaggableOn::TagList).should be_true
-
- lambda {
- @taggable.save
- }.should change(ActsAsTaggableOn::Tag, :count).by(3)
-
- @taggable.reload
- @taggable.skill_list.sort.should == %w(ruby rails css).sort
- end
-
- it "should be able to create tags through the tag list directly" do
- @taggable.tag_list_on(:test).add("hello")
- @taggable.tag_list_cache_on(:test).should_not be_empty
- @taggable.tag_list_on(:test).should == ["hello"]
-
- @taggable.save
- @taggable.save_tags
-
- @taggable.reload
- @taggable.tag_list_on(:test).should == ["hello"]
- end
-
- it "should differentiate between contexts" do
- @taggable.skill_list = "ruby, rails, css"
- @taggable.tag_list = "ruby, bob, charlie"
- @taggable.save
- @taggable.reload
- @taggable.skill_list.should include("ruby")
- @taggable.skill_list.should_not include("bob")
- end
-
- it "should be able to remove tags through list alone" do
- @taggable.skill_list = "ruby, rails, css"
- @taggable.save
- @taggable.reload
- @taggable.should have(3).skills
- @taggable.skill_list = "ruby, rails"
- @taggable.save
- @taggable.reload
- @taggable.should have(2).skills
- end
-
- it "should be able to select taggables by subset of tags using ActiveRelation methods" do
- @taggables[0].tag_list = "bob"
- @taggables[1].tag_list = "charlie"
- @taggables[0].skill_list = "ruby"
- @taggables[1].skill_list = "css"
- @taggables.each{|taggable| taggable.save}
-
- @found_taggables_by_tag = TaggableModel.joins(:tags).where(:tags => {:name => ["bob"]})
- @found_taggables_by_skill = TaggableModel.joins(:skills).where(:tags => {:name => ["ruby"]})
-
- @found_taggables_by_tag.should include @taggables[0]
- @found_taggables_by_tag.should_not include @taggables[1]
- @found_taggables_by_skill.should include @taggables[0]
- @found_taggables_by_skill.should_not include @taggables[1]
- end
-
- it "should be able to find by tag" do
- @taggable.skill_list = "ruby, rails, css"
- @taggable.save
-
- TaggableModel.tagged_with("ruby").first.should == @taggable
- end
-
- it "should be able to find by tag with context" do
- @taggable.skill_list = "ruby, rails, css"
- @taggable.tag_list = "bob, charlie"
- @taggable.save
-
- TaggableModel.tagged_with("ruby").first.should == @taggable
- TaggableModel.tagged_with("ruby, css").first.should == @taggable
- TaggableModel.tagged_with("bob", :on => :skills).first.should_not == @taggable
- TaggableModel.tagged_with("bob", :on => :tags).first.should == @taggable
- end
-
- it "should not care about case" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "Ruby")
-
- ActsAsTaggableOn::Tag.all.size.should == 1
- TaggableModel.tagged_with("ruby").to_a.should == TaggableModel.tagged_with("Ruby").to_a
- end
-
- it "should be able to get tag counts on model as a whole" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
- charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby")
- TaggableModel.tag_counts.should_not be_empty
- TaggableModel.skill_counts.should_not be_empty
- end
-
- it "should be able to get all tag counts on model as whole" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
- charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby")
-
- TaggableModel.all_tag_counts.should_not be_empty
- TaggableModel.all_tag_counts(:order => 'tags.id').first.count.should == 3 # ruby
- end
-
- it "should be able to get all tags on model as whole" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
- charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby")
-
- TaggableModel.all_tags.should_not be_empty
- TaggableModel.all_tags(:order => 'tags.id').first.name.should == "ruby"
- end
-
- it "should be able to use named scopes to chain tag finds by any tags by context" do
- bob = TaggableModel.create(:name => "Bob", :need_list => "rails", :offering_list => "c++")
- frank = TaggableModel.create(:name => "Frank", :need_list => "css", :offering_list => "css")
- steve = TaggableModel.create(:name => 'Steve', :need_list => "c++", :offering_list => "java")
-
- # Let's only find those who need rails or css and are offering c++ or java
- TaggableModel.tagged_with(['rails, css'], :on => :needs, :any => true).tagged_with(['c++', 'java'], :on => :offerings, :any => true).to_a.should == [bob]
- end
-
- it "should not return read-only records" do
- TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
- TaggableModel.tagged_with("ruby").first.should_not be_readonly
- end
-
- it "should be able to get scoped tag counts" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
- charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby")
-
- TaggableModel.tagged_with("ruby").tag_counts(:order => 'tags.id').first.count.should == 2 # ruby
- TaggableModel.tagged_with("ruby").skill_counts.first.count.should == 1 # ruby
- end
-
- it "should be able to get all scoped tag counts" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
- charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby")
-
- TaggableModel.tagged_with("ruby").all_tag_counts(:order => 'tags.id').first.count.should == 3 # ruby
- end
-
- it "should be able to get all scoped tags" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
- charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby")
-
- TaggableModel.tagged_with("ruby").all_tags(:order => 'tags.id').first.name.should == "ruby"
- end
-
- it 'should only return tag counts for the available scope' do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
- charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby, java")
-
- TaggableModel.tagged_with('rails').all_tag_counts.should have(3).items
- TaggableModel.tagged_with('rails').all_tag_counts.any? { |tag| tag.name == 'java' }.should be_false
-
- # Test specific join syntaxes:
- frank.untaggable_models.create!
- TaggableModel.tagged_with('rails').joins(:untaggable_models).all_tag_counts.should have(2).items
- TaggableModel.tagged_with('rails').joins(:untaggable_models => :taggable_model).all_tag_counts.should have(2).items
- TaggableModel.tagged_with('rails').joins([:untaggable_models]).all_tag_counts.should have(2).items
- end
-
- it 'should only return tags for the available scope' do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "ruby, rails")
- charlie = TaggableModel.create(:name => "Charlie", :skill_list => "ruby, java")
-
- TaggableModel.tagged_with('rails').all_tags.should have(3).items
- TaggableModel.tagged_with('rails').all_tags.any? { |tag| tag.name == 'java' }.should be_false
-
- # Test specific join syntaxes:
- frank.untaggable_models.create!
- TaggableModel.tagged_with('rails').joins(:untaggable_models).all_tags.should have(2).items
- TaggableModel.tagged_with('rails').joins({ :untaggable_models => :taggable_model }).all_tags.should have(2).items
- TaggableModel.tagged_with('rails').joins([:untaggable_models]).all_tags.should have(2).items
- end
-
- it "should be able to set a custom tag context list" do
- bob = TaggableModel.create(:name => "Bob")
- bob.set_tag_list_on(:rotors, "spinning, jumping")
- bob.tag_list_on(:rotors).should == ["spinning","jumping"]
- bob.save
- bob.reload
- bob.tags_on(:rotors).should_not be_empty
- end
-
- it "should be able to find tagged" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "fitter, happier, more productive", :skill_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "weaker, depressed, inefficient", :skill_list => "ruby, rails, css")
- steve = TaggableModel.create(:name => 'Steve', :tag_list => 'fitter, happier, more productive', :skill_list => 'c++, java, ruby')
-
- TaggableModel.tagged_with("ruby", :order => 'taggable_models.name').to_a.should == [bob, frank, steve]
- TaggableModel.tagged_with("ruby, rails", :order => 'taggable_models.name').to_a.should == [bob, frank]
- TaggableModel.tagged_with(["ruby", "rails"], :order => 'taggable_models.name').to_a.should == [bob, frank]
- end
-
- it "should be able to find tagged with quotation marks" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "fitter, happier, more productive, 'I love the ,comma,'")
- TaggableModel.tagged_with("'I love the ,comma,'").should include(bob)
- end
-
- it "should be able to find tagged with invalid tags" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "fitter, happier, more productive")
- TaggableModel.tagged_with("sad, happier").should_not include(bob)
- end
-
- it "should be able to find tagged with any tag" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "fitter, happier, more productive", :skill_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "weaker, depressed, inefficient", :skill_list => "ruby, rails, css")
- steve = TaggableModel.create(:name => 'Steve', :tag_list => 'fitter, happier, more productive', :skill_list => 'c++, java, ruby')
-
- TaggableModel.tagged_with(["ruby", "java"], :order => 'taggable_models.name', :any => true).to_a.should == [bob, frank, steve]
- TaggableModel.tagged_with(["c++", "fitter"], :order => 'taggable_models.name', :any => true).to_a.should == [bob, steve]
- TaggableModel.tagged_with(["depressed", "css"], :order => 'taggable_models.name', :any => true).to_a.should == [bob, frank]
- end
-
- context "wild: true" do
- it "should use params as wildcards" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "bob, tricia")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "bobby, jim")
- steve = TaggableModel.create(:name => "Steve", :tag_list => "john, patricia")
- jim = TaggableModel.create(:name => "Jim", :tag_list => "jim, steve")
-
-
- TaggableModel.tagged_with(["bob", "tricia"], :wild => true, :any => true).to_a.sort_by{|o| o.id}.should == [bob, frank, steve]
- TaggableModel.tagged_with(["bob", "tricia"], :wild => true, :exclude => true).to_a.should == [jim]
- end
- end
-
- it "should be able to find tagged on a custom tag context" do
- bob = TaggableModel.create(:name => "Bob")
- bob.set_tag_list_on(:rotors, "spinning, jumping")
- bob.tag_list_on(:rotors).should == ["spinning","jumping"]
- bob.save
-
- TaggableModel.tagged_with("spinning", :on => :rotors).to_a.should == [bob]
- end
-
- it "should be able to use named scopes to chain tag finds" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "fitter, happier, more productive", :skill_list => "ruby, rails, css")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "weaker, depressed, inefficient", :skill_list => "ruby, rails, css")
- steve = TaggableModel.create(:name => 'Steve', :tag_list => 'fitter, happier, more productive', :skill_list => 'c++, java, python')
-
- # Let's only find those productive Rails developers
- TaggableModel.tagged_with('rails', :on => :skills, :order => 'taggable_models.name').to_a.should == [bob, frank]
- TaggableModel.tagged_with('happier', :on => :tags, :order => 'taggable_models.name').to_a.should == [bob, steve]
- TaggableModel.tagged_with('rails', :on => :skills).tagged_with('happier', :on => :tags).to_a.should == [bob]
- TaggableModel.tagged_with('rails').tagged_with('happier', :on => :tags).to_a.should == [bob]
- end
-
- it "should be able to find tagged with only the matching tags" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "lazy, happier")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "fitter, happier, inefficient")
- steve = TaggableModel.create(:name => 'Steve', :tag_list => "fitter, happier")
-
- TaggableModel.tagged_with("fitter, happier", :match_all => true).to_a.should == [steve]
- end
-
- it "should be able to find tagged with some excluded tags" do
- bob = TaggableModel.create(:name => "Bob", :tag_list => "happier, lazy")
- frank = TaggableModel.create(:name => "Frank", :tag_list => "happier")
- steve = TaggableModel.create(:name => 'Steve', :tag_list => "happier")
-
- TaggableModel.tagged_with("lazy", :exclude => true).to_a.should == [frank, steve]
- end
-
- it "should return an empty scope for empty tags" do
- TaggableModel.tagged_with('').should == []
- TaggableModel.tagged_with(' ').should == []
- TaggableModel.tagged_with(nil).should == []
- TaggableModel.tagged_with([]).should == []
- end
-
- it "should not create duplicate taggings" do
- bob = TaggableModel.create(:name => "Bob")
- lambda {
- bob.tag_list << "happier"
- bob.tag_list << "happier"
- bob.save
- }.should change(ActsAsTaggableOn::Tagging, :count).by(1)
- end
-
- describe "Associations" do
- before(:each) do
- @taggable = TaggableModel.create(:tag_list => "awesome, epic")
- end
-
- it "should not remove tags when creating associated objects" do
- @taggable.untaggable_models.create!
- @taggable.reload
- @taggable.tag_list.should have(2).items
- end
- end
-
- describe "grouped_column_names_for method" do
- it "should return all column names joined for Tag GROUP clause" do
- @taggable.grouped_column_names_for(ActsAsTaggableOn::Tag).should == "tags.id, tags.name"
- end
-
- it "should return all column names joined for TaggableModel GROUP clause" do
- @taggable.grouped_column_names_for(TaggableModel).should == "taggable_models.id, taggable_models.name, taggable_models.type"
- end
-
- it "should return all column names joined for NonStandardIdTaggableModel GROUP clause" do
- @taggable.grouped_column_names_for(TaggableModel).should == "taggable_models.#{TaggableModel.primary_key}, taggable_models.name, taggable_models.type"
- end
- end
-
- describe "NonStandardIdTaggable" do
- before(:each) do
- clean_database!
- @taggable = NonStandardIdTaggableModel.new(:name => "Bob Jones")
- @taggables = [@taggable, NonStandardIdTaggableModel.new(:name => "John Doe")]
- end
-
- it "should have tag types" do
- [:tags, :languages, :skills, :needs, :offerings].each do |type|
- NonStandardIdTaggableModel.tag_types.should include type
- end
-
- @taggable.tag_types.should == NonStandardIdTaggableModel.tag_types
- end
-
- it "should have tag_counts_on" do
- NonStandardIdTaggableModel.tag_counts_on(:tags).should be_empty
-
- @taggable.tag_list = ["awesome", "epic"]
- @taggable.save
-
- NonStandardIdTaggableModel.tag_counts_on(:tags).length.should == 2
- @taggable.tag_counts_on(:tags).length.should == 2
- end
-
- it "should have tags_on" do
- NonStandardIdTaggableModel.tags_on(:tags).should be_empty
-
- @taggable.tag_list = ["awesome", "epic"]
- @taggable.save
-
- NonStandardIdTaggableModel.tags_on(:tags).length.should == 2
- @taggable.tags_on(:tags).length.should == 2
- end
-
- it "should be able to create tags" do
- @taggable.skill_list = "ruby, rails, css"
- @taggable.instance_variable_get("@skill_list").instance_of?(ActsAsTaggableOn::TagList).should be_true
-
- lambda {
- @taggable.save
- }.should change(ActsAsTaggableOn::Tag, :count).by(3)
-
- @taggable.reload
- @taggable.skill_list.sort.should == %w(ruby rails css).sort
- end
-
- it "should be able to create tags through the tag list directly" do
- @taggable.tag_list_on(:test).add("hello")
- @taggable.tag_list_cache_on(:test).should_not be_empty
- @taggable.tag_list_on(:test).should == ["hello"]
-
- @taggable.save
- @taggable.save_tags
-
- @taggable.reload
- @taggable.tag_list_on(:test).should == ["hello"]
- end
- end
-
- describe "Dirty Objects" do
- context "with un-contexted tags" do
- before(:each) do
- @taggable = TaggableModel.create(:tag_list => "awesome, epic")
- end
-
- context "when tag_list changed" do
- before(:each) do
- @taggable.changes.should == {}
- @taggable.tag_list = 'one'
- end
-
- it 'should show changes of dirty object' do
- @taggable.changes.should == {"tag_list"=>["awesome, epic", ["one"]]}
- end
-
- it 'flags tag_list as changed' do
- @taggable.tag_list_changed?.should be_true
- end
-
- it 'preserves original value' do
- @taggable.tag_list_was.should == "awesome, epic"
- end
-
- it 'shows what the change was' do
- @taggable.tag_list_change.should == ["awesome, epic", ["one"]]
- end
- end
-
- context 'when tag_list is the same' do
- before(:each) do
- @taggable.tag_list = "awesome, epic"
- end
-
- it 'is not flagged as changed' do
- @taggable.tag_list_changed?.should be_false
- end
-
- it 'does not show any changes to the taggable item' do
- @taggable.changes.should == {}
- end
- end
- end
-
- context "with context tags" do
- before(:each) do
- @taggable = TaggableModel.create(:language_list => "awesome, epic")
- end
-
- context "when language_list changed" do
- before(:each) do
- @taggable.changes.should == {}
- @taggable.language_list = 'one'
- end
-
- it 'should show changes of dirty object' do
- @taggable.changes.should == {"language_list"=>["awesome, epic", ["one"]]}
- end
-
- it 'flags language_list as changed' do
- @taggable.language_list_changed?.should be_true
- end
-
- it 'preserves original value' do
- @taggable.language_list_was.should == "awesome, epic"
- end
-
- it 'shows what the change was' do
- @taggable.language_list_change.should == ["awesome, epic", ["one"]]
- end
-
- it 'shows what the changes were' do
- @taggable.language_list_changes.should == ["awesome, epic", ["one"]]
- end
- end
-
- context 'when language_list is the same' do
- before(:each) do
- @taggable.language_list = "awesome, epic"
- end
-
- it 'is not flagged as changed' do
- @taggable.language_list_changed?.should be_false
- end
-
- it 'does not show any changes to the taggable item' do
- @taggable.changes.should == {}
- end
- end
- end
- end
-
- describe "Autogenerated methods" do
- it "should be overridable" do
- TaggableModel.create(:tag_list=>'woo').tag_list_submethod_called.should be_true
- end
- end
-end
-
-
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tagger_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tagger_spec.rb
deleted file mode 100644
index ab0b2b91b..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tagger_spec.rb
+++ /dev/null
@@ -1,137 +0,0 @@
-require 'spec_helper'
-
-describe "Tagger" do
- before(:each) do
- clean_database!
- @user = User.create
- @taggable = TaggableModel.create(:name => "Bob Jones")
- end
-
- it "should have taggings" do
- @user.tag(@taggable, :with=>'ruby,scheme', :on=>:tags)
- @user.owned_taggings.size == 2
- end
-
- it "should have tags" do
- @user.tag(@taggable, :with=>'ruby,scheme', :on=>:tags)
- @user.owned_tags.size == 2
- end
-
- it "should scope objects returned by tagged_with by owners" do
- @taggable2 = TaggableModel.create(:name => "Jim Jones")
- @taggable3 = TaggableModel.create(:name => "Jane Doe")
-
- @user2 = User.new
- @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
- @user2.tag(@taggable2, :with => 'ruby, scheme', :on => :tags)
- @user2.tag(@taggable3, :with => 'ruby, scheme', :on => :tags)
-
- TaggableModel.tagged_with(%w(ruby scheme), :owned_by => @user).count.should == 1
- TaggableModel.tagged_with(%w(ruby scheme), :owned_by => @user2).count.should == 2
- end
-
- it "only returns objects tagged by owned_by when any is true" do
- @user2 = User.new
- @taggable2 = TaggableModel.create(:name => "Jim Jones")
- @taggable3 = TaggableModel.create(:name => "Jane Doe")
-
- @user.tag(@taggable, :with => 'ruby', :on => :tags)
- @user.tag(@taggable2, :with => 'java', :on => :tags)
- @user2.tag(@taggable3, :with => 'ruby', :on => :tags)
-
- tags = TaggableModel.tagged_with(%w(ruby java), :owned_by => @user, :any => true)
- tags.should match_array [@taggable, @taggable2]
- end
-
- it "only returns objects tagged by owned_by when exclude is true" do
- @user2 = User.new
- @taggable2 = TaggableModel.create(:name => "Jim Jones")
- @taggable3 = TaggableModel.create(:name => "Jane Doe")
-
- @user.tag(@taggable, :with => 'ruby', :on => :tags)
- @user.tag(@taggable2, :with => 'java', :on => :tags)
- @user2.tag(@taggable3, :with => 'java', :on => :tags)
-
- tags = TaggableModel.tagged_with(%w(ruby), :owned_by => @user, :exclude => true)
- tags.should match_array [@taggable2]
- end
-
- it "should not overlap tags from different taggers" do
- @user2 = User.new
- lambda{
- @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
- @user2.tag(@taggable, :with => 'java, python, lisp, ruby', :on => :tags)
- }.should change(ActsAsTaggableOn::Tagging, :count).by(6)
-
- [@user, @user2, @taggable].each(&:reload)
-
- @user.owned_tags.map(&:name).sort.should == %w(ruby scheme).sort
- @user2.owned_tags.map(&:name).sort.should == %w(java python lisp ruby).sort
-
- @taggable.tags_from(@user).sort.should == %w(ruby scheme).sort
- @taggable.tags_from(@user2).sort.should == %w(java lisp python ruby).sort
-
- @taggable.all_tags_list.sort.should == %w(ruby scheme java python lisp).sort
- @taggable.all_tags_on(:tags).size.should == 5
- end
-
- it "should not lose tags from different taggers" do
- @user2 = User.create
- @user2.tag(@taggable, :with => 'java, python, lisp, ruby', :on => :tags)
- @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
-
- lambda {
- @user2.tag(@taggable, :with => 'java, python, lisp', :on => :tags)
- }.should change(ActsAsTaggableOn::Tagging, :count).by(-1)
-
- [@user, @user2, @taggable].each(&:reload)
-
- @taggable.tags_from(@user).sort.should == %w(ruby scheme).sort
- @taggable.tags_from(@user2).sort.should == %w(java python lisp).sort
-
- @taggable.all_tags_list.sort.should == %w(ruby scheme java python lisp).sort
- @taggable.all_tags_on(:tags).length.should == 5
- end
-
- it "should not lose tags" do
- @user2 = User.create
-
- @user.tag(@taggable, :with => 'awesome', :on => :tags)
- @user2.tag(@taggable, :with => 'awesome, epic', :on => :tags)
-
- lambda {
- @user2.tag(@taggable, :with => 'epic', :on => :tags)
- }.should change(ActsAsTaggableOn::Tagging, :count).by(-1)
-
- @taggable.reload
- @taggable.all_tags_list.should include('awesome')
- @taggable.all_tags_list.should include('epic')
- end
-
- it "should not lose tags" do
- @taggable.update_attributes(:tag_list => 'ruby')
- @user.tag(@taggable, :with => 'ruby, scheme', :on => :tags)
-
- [@taggable, @user].each(&:reload)
- @taggable.tag_list.should == %w(ruby)
- @taggable.all_tags_list.sort.should == %w(ruby scheme).sort
-
- lambda {
- @taggable.update_attributes(:tag_list => "")
- }.should change(ActsAsTaggableOn::Tagging, :count).by(-1)
-
- @taggable.tag_list.should == []
- @taggable.all_tags_list.sort.should == %w(ruby scheme).sort
- end
-
- it "is tagger" do
- @user.is_tagger?.should(be_true)
- end
-
- it "should skip save if skip_save is passed as option" do
- lambda {
- @user.tag(@taggable, :with => 'epic', :on => :tags, :skip_save => true)
- }.should_not change(ActsAsTaggableOn::Tagging, :count)
- end
-
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tagging_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tagging_spec.rb
deleted file mode 100644
index 7b5649260..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tagging_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require 'spec_helper'
-
-describe ActsAsTaggableOn::Tagging do
- before(:each) do
- clean_database!
- @tagging = ActsAsTaggableOn::Tagging.new
- end
-
- it "should not be valid with a invalid tag" do
- @tagging.taggable = TaggableModel.create(:name => "Bob Jones")
- @tagging.tag = ActsAsTaggableOn::Tag.new(:name => "")
- @tagging.context = "tags"
-
- @tagging.should_not be_valid
-
- @tagging.errors[:tag_id].should == ["can't be blank"]
- end
-
- it "should not create duplicate taggings" do
- @taggable = TaggableModel.create(:name => "Bob Jones")
- @tag = ActsAsTaggableOn::Tag.create(:name => "awesome")
-
- lambda {
- 2.times { ActsAsTaggableOn::Tagging.create(:taggable => @taggable, :tag => @tag, :context => 'tags') }
- }.should change(ActsAsTaggableOn::Tagging, :count).by(1)
- end
-
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tags_helper_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tags_helper_spec.rb
deleted file mode 100644
index 089f89390..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/tags_helper_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require 'spec_helper'
-
-describe ActsAsTaggableOn::TagsHelper do
- before(:each) do
- clean_database!
-
- @bob = TaggableModel.create(:name => "Bob Jones", :language_list => "ruby, php")
- @tom = TaggableModel.create(:name => "Tom Marley", :language_list => "ruby, java")
- @eve = TaggableModel.create(:name => "Eve Nodd", :language_list => "ruby, c++")
-
- @helper = class Helper
- include ActsAsTaggableOn::TagsHelper
- end.new
- end
-
- it "should yield the proper css classes" do
- tags = { }
-
- @helper.tag_cloud(TaggableModel.tag_counts_on(:languages), ["sucky", "awesome"]) do |tag, css_class|
- tags[tag.name] = css_class
- end
-
- tags["ruby"].should == "awesome"
- tags["java"].should == "sucky"
- tags["c++"].should == "sucky"
- tags["php"].should == "sucky"
- end
-
- it "should handle tags with zero counts (build for empty)" do
- bob = ActsAsTaggableOn::Tag.create(:name => "php")
- tom = ActsAsTaggableOn::Tag.create(:name => "java")
- eve = ActsAsTaggableOn::Tag.create(:name => "c++")
-
- tags = { }
-
- @helper.tag_cloud(ActsAsTaggableOn::Tag.all, ["sucky", "awesome"]) do |tag, css_class|
- tags[tag.name] = css_class
- end
-
- tags["java"].should == "sucky"
- tags["c++"].should == "sucky"
- tags["php"].should == "sucky"
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/utils_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/utils_spec.rb
deleted file mode 100644
index 75af44419..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/acts_as_taggable_on/utils_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'spec_helper'
-
-describe ActsAsTaggableOn::Utils do
- describe "like_operator" do
- before(:each) do
- clean_database!
- TaggableModel.acts_as_taggable_on(:tags, :languages, :skills, :needs, :offerings)
- @taggable = TaggableModel.new(:name => "Bob Jones")
- end
-
- it "should return 'ILIKE' when the adapter is PostgreSQL" do
- TaggableModel.connection.stub(:adapter_name).and_return("PostgreSQL")
- TaggableModel.send(:like_operator).should == "ILIKE"
- end
-
- it "should return 'LIKE' when the adapter is not PostgreSQL" do
- TaggableModel.connection.stub(:adapter_name).and_return("MySQL")
- TaggableModel.send(:like_operator).should == "LIKE"
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/bm.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/bm.rb
deleted file mode 100644
index 949dd475f..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/bm.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require 'active_record'
-require 'action_view'
-require File.expand_path('../../lib/acts-as-taggable-on', __FILE__)
-
-if defined?(ActiveRecord::Acts::TaggableOn)
- ActiveRecord::Base.send :include, ActiveRecord::Acts::TaggableOn
- ActiveRecord::Base.send :include, ActiveRecord::Acts::Tagger
- ActionView::Base.send :include, TagsHelper if defined?(ActionView::Base)
-end
-
-TEST_DATABASE_FILE = File.join(File.dirname(__FILE__), '..', 'test.sqlite3')
-File.unlink(TEST_DATABASE_FILE) if File.exist?(TEST_DATABASE_FILE)
-ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => TEST_DATABASE_FILE
-
-ActiveRecord::Base.silence do
- ActiveRecord::Migration.verbose = false
- ActiveRecord::Schema.define :version => 0 do
- create_table "taggings", :force => true do |t|
- t.integer "tag_id", :limit => 11
- t.integer "taggable_id", :limit => 11
- t.string "taggable_type"
- t.string "context"
- t.datetime "created_at"
- t.integer "tagger_id", :limit => 11
- t.string "tagger_type"
- end
-
- add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
- add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
-
- create_table "tags", :force => true do |t|
- t.string "name"
- end
-
- create_table :taggable_models, :force => true do |t|
- t.column :name, :string
- t.column :type, :string
- t.column :cached_tag_list, :string
- end
- end
-
- class TaggableModel < ActiveRecord::Base
- acts_as_taggable
- acts_as_taggable_on :languages
- acts_as_taggable_on :skills
- acts_as_taggable_on :needs, :offerings
- end
-end
-
-puts Benchmark.measure {
- 1000.times { TaggableModel.create :tag_list => "awesome, epic, neat" }
-}
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/database.yml.sample b/trustie2/lib/plugins/acts-as-taggable-on/spec/database.yml.sample
deleted file mode 100644
index 97652ed57..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/database.yml.sample
+++ /dev/null
@@ -1,19 +0,0 @@
-sqlite3:
- adapter: sqlite3
- database: acts_as_taggable_on.sqlite3
-
-mysql:
- adapter: mysql2
- hostname: localhost
- username: root
- password:
- database: acts_as_taggable_on
- charset: utf8
-
-postgresql:
- adapter: postgresql
- hostname: localhost
- username: postgres
- password:
- database: acts_as_taggable_on
- encoding: utf8
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb
deleted file mode 100644
index bc7894bde..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/generators/acts_as_taggable_on/migration/migration_generator_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'spec_helper'
-
-# Generators are not automatically loaded by Rails
-require 'generators/acts_as_taggable_on/migration/migration_generator'
-
-describe ActsAsTaggableOn::MigrationGenerator do
- # Tell the generator where to put its output (what it thinks of as Rails.root)
- destination File.expand_path("../../../../../tmp", __FILE__)
-
- before do
- prepare_destination
- Rails::Generators.options[:rails][:orm] = :active_record
- end
- describe 'no arguments' do
- before { run_generator }
-
- describe 'db/migrate/acts_as_taggable_on_migration.rb' do
- title { file('db/migrate/acts_as_taggable_on_migration.rb') }
- it { should be_a_migration }
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/models.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/models.rb
deleted file mode 100644
index 133d4765c..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/models.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-class TaggableModel < ActiveRecord::Base
- acts_as_taggable
- acts_as_taggable_on :languages
- acts_as_taggable_on :skills
- acts_as_taggable_on :needs, :offerings
- has_many :untaggable_models
-
- attr_reader :tag_list_submethod_called
- def tag_list=v
- @tag_list_submethod_called = true
- super
- end
-end
-
-class CachedModel < ActiveRecord::Base
- acts_as_taggable
-end
-
-class OtherCachedModel < ActiveRecord::Base
- acts_as_taggable_on :languages, :statuses, :glasses
-end
-
-class OtherTaggableModel < ActiveRecord::Base
- acts_as_taggable_on :tags, :languages
- acts_as_taggable_on :needs, :offerings
-end
-
-class InheritingTaggableModel < TaggableModel
-end
-
-class AlteredInheritingTaggableModel < TaggableModel
- acts_as_taggable_on :parts
-end
-
-class User < ActiveRecord::Base
- acts_as_tagger
-end
-
-class Student < User
-end
-
-class UntaggableModel < ActiveRecord::Base
- belongs_to :taggable_model
-end
-
-class NonStandardIdTaggableModel < ActiveRecord::Base
- primary_key = "an_id"
- acts_as_taggable
- acts_as_taggable_on :languages
- acts_as_taggable_on :skills
- acts_as_taggable_on :needs, :offerings
- has_many :untaggable_models
-end
-
-class OrderedTaggableModel < ActiveRecord::Base
- acts_as_ordered_taggable
- acts_as_ordered_taggable_on :colours
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/schema.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/schema.rb
deleted file mode 100644
index 4949f0107..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/schema.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-ActiveRecord::Schema.define :version => 0 do
- create_table "taggings", :force => true do |t|
- t.integer "tag_id", :limit => 11
- t.integer "taggable_id", :limit => 11
- t.string "taggable_type"
- t.string "context"
- t.datetime "created_at"
- t.integer "tagger_id", :limit => 11
- t.string "tagger_type"
- end
-
- add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
- add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
-
- create_table "tags", :force => true do |t|
- t.string "name"
- end
-
- create_table :taggable_models, :force => true do |t|
- t.column :name, :string
- t.column :type, :string
- end
-
- create_table :non_standard_id_taggable_models, :primary_key => "an_id", :force => true do |t|
- t.column :name, :string
- t.column :type, :string
- end
-
- create_table :untaggable_models, :force => true do |t|
- t.column :taggable_model_id, :integer
- t.column :name, :string
- end
-
- create_table :cached_models, :force => true do |t|
- t.column :name, :string
- t.column :type, :string
- t.column :cached_tag_list, :string
- end
-
- create_table :other_cached_models, :force => true do |t|
- t.column :name, :string
- t.column :type, :string
- t.column :cached_language_list, :string
- t.column :cached_status_list, :string
- t.column :cached_glass_list, :string
- end
-
- create_table :users, :force => true do |t|
- t.column :name, :string
- end
-
- create_table :other_taggable_models, :force => true do |t|
- t.column :name, :string
- t.column :type, :string
- end
-
- create_table :ordered_taggable_models, :force => true do |t|
- t.column :name, :string
- t.column :type, :string
- end
-end
diff --git a/trustie2/lib/plugins/acts-as-taggable-on/spec/spec_helper.rb b/trustie2/lib/plugins/acts-as-taggable-on/spec/spec_helper.rb
deleted file mode 100644
index e317bc319..000000000
--- a/trustie2/lib/plugins/acts-as-taggable-on/spec/spec_helper.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-$LOAD_PATH << "." unless $LOAD_PATH.include?(".")
-require 'logger'
-
-begin
- require "rubygems"
- require "bundler"
-
- if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.5")
- raise RuntimeError, "Your bundler version is too old." +
- "Run `gem install bundler` to upgrade."
- end
-
- # Set up load paths for all bundled gems
- Bundler.setup
-rescue Bundler::GemNotFound
- raise RuntimeError, "Bundler couldn't find some gems." +
- "Did you run \`bundlee install\`?"
-end
-
-Bundler.require
-require File.expand_path('../../lib/acts-as-taggable-on', __FILE__)
-require 'ammeter/init'
-
-unless [].respond_to?(:freq)
- class Array
- def freq
- k=Hash.new(0)
- each {|e| k[e]+=1}
- k
- end
- end
-end
-
-# set adapter to use, default is sqlite3
-# to use an alternative adapter run => rake spec DB='postgresql'
-db_name = ENV['DB'] || 'sqlite3'
-database_yml = File.expand_path('../database.yml', __FILE__)
-
-if File.exists?(database_yml)
- active_record_configuration = YAML.load_file(database_yml)
-
- ActiveRecord::Base.configurations = active_record_configuration
- config = ActiveRecord::Base.configurations[db_name]
-
- begin
- ActiveRecord::Base.establish_connection(db_name)
- ActiveRecord::Base.connection
- rescue
- case db_name
- when /mysql/
- ActiveRecord::Base.establish_connection(config.merge('database' => nil))
- ActiveRecord::Base.connection.create_database(config['database'], {:charset => 'utf8', :collation => 'utf8_unicode_ci'})
- when 'postgresql'
- ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
- ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => 'utf8'))
- end
-
- ActiveRecord::Base.establish_connection(config)
- end
-
- logger = ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
- ActiveRecord::Base.default_timezone = :utc
-
- begin
- old_logger_level, logger.level = logger.level, ::Logger::ERROR
- ActiveRecord::Migration.verbose = false
-
- load(File.dirname(__FILE__) + '/schema.rb')
- load(File.dirname(__FILE__) + '/models.rb')
- ensure
- logger.level = old_logger_level
- end
-
-else
- raise "Please create #{database_yml} first to configure your database. Take a look at: #{database_yml}.sample"
-end
-
-def clean_database!
- models = [ActsAsTaggableOn::Tag, ActsAsTaggableOn::Tagging, TaggableModel, OtherTaggableModel, InheritingTaggableModel,
- AlteredInheritingTaggableModel, User, UntaggableModel, OrderedTaggableModel]
- models.each do |model|
- ActiveRecord::Base.connection.execute "DELETE FROM #{model.table_name}"
- end
-end
-
-clean_database!
diff --git a/trustie2/lib/plugins/acts_as_activity_provider/init.rb b/trustie2/lib/plugins/acts_as_activity_provider/init.rb
deleted file mode 100644
index 5bf05da2c..000000000
--- a/trustie2/lib/plugins/acts_as_activity_provider/init.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require File.dirname(__FILE__) + '/lib/acts_as_activity_provider'
-ActiveRecord::Base.send(:include, Redmine::Acts::ActivityProvider)
diff --git a/trustie2/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb b/trustie2/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb
deleted file mode 100644
index 78613f4b8..000000000
--- a/trustie2/lib/plugins/acts_as_activity_provider/lib/acts_as_activity_provider.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Acts
- module ActivityProvider
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- def acts_as_activity_provider(options = {})
- unless self.included_modules.include?(Redmine::Acts::ActivityProvider::InstanceMethods)
- cattr_accessor :activity_provider_options
- send :include, Redmine::Acts::ActivityProvider::InstanceMethods
- end
-
- options.assert_valid_keys(:type, :permission, :timestamp, :author_key, :find_options, :func)
- self.activity_provider_options ||= {}
-
- # One model can provide different event types
- # We store these options in activity_provider_options hash
- event_type = options.delete(:type) || self.name.underscore.pluralize
-
- options[:timestamp] ||= "#{table_name}.created_on"
- options[:find_options] ||= {}
- options[:author_key] = "#{table_name}.#{options[:author_key]}" if options[:author_key].is_a?(Symbol)
- self.activity_provider_options[event_type] = options
- end
- end
-
- module InstanceMethods
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- # Returns events of type event_type visible by user that occured between from and to
- def find_events(event_type, user, from, to, options)
- provider_options = activity_provider_options[event_type]
- raise "#{self.name} can not provide #{event_type} events." if provider_options.nil?
-
- scope = self
-
- if from && to
- scope = scope.scoped(:conditions => ["#{provider_options[:timestamp]} BETWEEN ? AND ?", from, to])
- end
-
- if options[:author]
- return [] if provider_options[:author_key].nil?
- scope = scope.scoped(:conditions => ["#{provider_options[:author_key]} = ?", options[:author].id])
- end
-
- if options[:limit]
- # id and creation time should be in same order in most cases
- scope = scope.scoped(:order => "#{table_name}.id DESC", :limit => options[:limit])
- end
-
- if provider_options.has_key?(:permission)
- scope = scope.scoped(:conditions => Project.allowed_to_condition(user, provider_options[:permission] || :view_project, options))
- elsif respond_to?(:visible)
- scope = scope.visible(user, options)
- else
- ActiveSupport::Deprecation.warn "acts_as_activity_provider with implicit :permission option is deprecated. Add a visible scope to the #{self.name} model or use explicit :permission option."
- scope = scope.scoped(:conditions => Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym, options))
- end
-
- scope.all(provider_options[:find_options].dup)
- end
-
- # 为了首页获取数据基本复制了上面的方法,改变了用户查看权限,增加了对讨论区的识别。
- # 因为新建了讨论区的内容,没有与项目方法混合,但是 event_type 取值类型还在共用,可能会对项目活动取值性能造成影响
- # 不过鉴于项目参与查询的条件减少,而增加的时间没有可见增长,重写event_type 的类型需要设计到lib,暂时不做改动
- def find_events1(event_type, user, from, to, options)
- provider_options = activity_provider_options[event_type]
- raise "#{self.name} can not provide #{event_type} events." if provider_options.nil?
-
- scope = self
- if from && to
- scope = scope.scoped(:conditions => ["#{provider_options[:timestamp]} BETWEEN ? AND ?", from, to])
- end
-
- if options[:author]
- return [] if provider_options[:author_key].nil?
- scope = scope.scoped(:conditions => ["#{provider_options[:author_key]} = ?", options[:author].id])
- end
-
- if options[:limit]
- # id and creation time should be in same order in most cases
- scope = scope.scoped(:order => "#{table_name}.id DESC", :limit => options[:limit])
- end
-
- user1 = User.find_by_admin(true)
- if provider_options.has_key?(:permission)
- scope = scope.scoped(:conditions => Project.allowed_to_condition(user1, provider_options[:permission] || :view_project, options))
- elsif respond_to?(:visible)
- scope = scope.visible(user1, options)
- elsif provider_options.has_key?(:func) && provider_options[:func].eql?('memos')
- scope = scope
- else
- ActiveSupport::Deprecation.warn "acts_as_activity_provider with implicit :permission option is deprecated. Add a visible scope to the #{self.name} model or use explicit :permission option."
- # scope = scope
- scope = scope.scoped(:conditions => Project.allowed_to_condition(user1, "view_#{self.name.underscore.pluralize}".to_sym, options))
- end
- scope.all(provider_options[:find_options].dup)
- end
-
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_attachable/init.rb b/trustie2/lib/plugins/acts_as_attachable/init.rb
deleted file mode 100644
index 213e1d4b1..000000000
--- a/trustie2/lib/plugins/acts_as_attachable/init.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require File.dirname(__FILE__) + '/lib/acts_as_attachable'
-ActiveRecord::Base.send(:include, Redmine::Acts::Attachable)
diff --git a/trustie2/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb b/trustie2/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb
deleted file mode 100644
index b37741bdf..000000000
--- a/trustie2/lib/plugins/acts_as_attachable/lib/acts_as_attachable.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Acts
- module Attachable
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- def acts_as_attachable(options = {})
- cattr_accessor :attachable_options
- self.attachable_options = {}
- attachable_options[:view_permission] = options.delete(:view_permission) || "view_#{self.name.pluralize.underscore}".to_sym
- attachable_options[:delete_permission] = options.delete(:delete_permission) || "edit_#{self.name.pluralize.underscore}".to_sym
- send :include, Redmine::Acts::Attachable::InstanceMethods
- end
- end
-
- module InstanceMethods
- def self.included(base)
- base.extend ClassMethods
- end
- module ClassMethods
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_customizable/init.rb b/trustie2/lib/plugins/acts_as_customizable/init.rb
deleted file mode 100644
index 9036aa579..000000000
--- a/trustie2/lib/plugins/acts_as_customizable/init.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require File.dirname(__FILE__) + '/lib/acts_as_customizable'
-ActiveRecord::Base.send(:include, Redmine::Acts::Customizable)
diff --git a/trustie2/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb b/trustie2/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb
deleted file mode 100644
index 1f1aa1e44..000000000
--- a/trustie2/lib/plugins/acts_as_customizable/lib/acts_as_customizable.rb
+++ /dev/null
@@ -1,168 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Acts
- module Customizable
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- def acts_as_customizable(options = {})
- return if self.included_modules.include?(Redmine::Acts::Customizable::InstanceMethods)
- cattr_accessor :customizable_options
- self.customizable_options = options
- has_many :custom_values, :as => :customized,
- :include => :custom_field,
- :order => "#{CustomField.table_name}.position",
- :dependent => :delete_all,
- :validate => false
-
- send :include, Redmine::Acts::Customizable::InstanceMethods
- validate :validate_custom_field_values
- after_save :save_custom_field_values
- end
- end
-
- module InstanceMethods
- def self.included(base)
- base.extend ClassMethods
- base.send :alias_method_chain, :reload, :custom_fields
- end
-
- def available_custom_fields
- CustomField.where("type = '#{self.class.name}CustomField'").sorted.all
- end
-
- # Sets the values of the object's custom fields
- # values is an array like [{'id' => 1, 'value' => 'foo'}, {'id' => 2, 'value' => 'bar'}]
- def custom_fields=(values)
- values_to_hash = values.inject({}) do |hash, v|
- v = v.stringify_keys
- if v['id'] && v.has_key?('value')
- hash[v['id']] = v['value']
- end
- hash
- end
- self.custom_field_values = values_to_hash
- end
-
- # Sets the values of the object's custom fields
- # values is a hash like {'1' => 'foo', 2 => 'bar'}
- def custom_field_values=(values)
- values = values.stringify_keys
-
- custom_field_values.each do |custom_field_value|
- key = custom_field_value.custom_field_id.to_s
- if values.has_key?(key)
- value = values[key]
- if value.is_a?(Array)
- value = value.reject(&:blank?).uniq
- if value.empty?
- value << ''
- end
- end
- custom_field_value.value = value
- end
- end
- @custom_field_values_changed = true
- end
-
- def custom_field_values
- @custom_field_values ||= available_custom_fields.collect do |field|
- x = CustomFieldValue.new
- x.custom_field = field
- x.customized = self
- if field.multiple?
- values = custom_values.select { |v| v.custom_field == field }
- if values.empty?
- values << custom_values.build(:customized => self, :custom_field => field, :value => nil)
- end
- x.value = values.map(&:value)
- else
- cv = custom_values.detect { |v| v.custom_field == field }
- cv ||= custom_values.build(:customized => self, :custom_field => field, :value => nil)
- x.value = cv.value
- end
- x
- end
- end
-
- def visible_custom_field_values
- custom_field_values.select(&:visible?)
- end
-
- def custom_field_values_changed?
- @custom_field_values_changed == true
- end
-
- def custom_value_for(c)
- field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
- custom_values.detect {|v| v.custom_field_id == field_id }
- end
-
- def custom_field_value(c)
- field_id = (c.is_a?(CustomField) ? c.id : c.to_i)
- custom_field_values.detect {|v| v.custom_field_id == field_id }.try(:value)
- end
-
- def validate_custom_field_values
- if new_record? || custom_field_values_changed?
- custom_field_values.each(&:validate_value)
- end
- end
-
- def save_custom_field_values
- target_custom_values = []
- custom_field_values.each do |custom_field_value|
- if custom_field_value.value.is_a?(Array)
- custom_field_value.value.each do |v|
- target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field && cv.value == v}
- target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field, :value => v)
- target_custom_values << target
- end
- else
- target = custom_values.detect {|cv| cv.custom_field == custom_field_value.custom_field}
- target ||= custom_values.build(:customized => self, :custom_field => custom_field_value.custom_field)
- target.value = custom_field_value.value
- target_custom_values << target
- end
- end
- self.custom_values = target_custom_values
- custom_values.each(&:save)
- @custom_field_values_changed = false
- true
- end
-
- def reset_custom_values!
- @custom_field_values = nil
- @custom_field_values_changed = true
- end
-
- def reload_with_custom_fields(*args)
- @custom_field_values = nil
- @custom_field_values_changed = false
- reload_without_custom_fields(*args)
- end
-
- module ClassMethods
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_event/init.rb b/trustie2/lib/plugins/acts_as_event/init.rb
deleted file mode 100644
index 91051510a..000000000
--- a/trustie2/lib/plugins/acts_as_event/init.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require File.dirname(__FILE__) + '/lib/acts_as_event'
-ActiveRecord::Base.send(:include, Redmine::Acts::Event)
diff --git a/trustie2/lib/plugins/acts_as_event/lib/acts_as_event.rb b/trustie2/lib/plugins/acts_as_event/lib/acts_as_event.rb
deleted file mode 100644
index e323c2b3e..000000000
--- a/trustie2/lib/plugins/acts_as_event/lib/acts_as_event.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Acts
- module Event
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- def acts_as_event(options = {})
- return if self.included_modules.include?(Redmine::Acts::Event::InstanceMethods)
- default_options = { :datetime => :created_on,
- :title => :title,
- :description => :description,
- :author => :author,
- :url => {:controller => 'welcome'},
- :type => self.name.underscore.dasherize }
-
- cattr_accessor :event_options
- self.event_options = default_options.merge(options)
- send :include, Redmine::Acts::Event::InstanceMethods
- end
- end
-
- module InstanceMethods
- def self.included(base)
- base.extend ClassMethods
- end
-
- %w(datetime title description author type).each do |attr|
- src = <<-END_SRC
- def event_#{attr}
- option = event_options[:#{attr}]
- if option.is_a?(Proc)
- option.call(self)
- elsif option.is_a?(Symbol)
- send(option)
- else
- option
- end
- end
- END_SRC
- class_eval src, __FILE__, __LINE__
- end
-
- def event_date
- event_datetime.to_date
- end
-
- def event_group
- group = event_options[:group] ? send(event_options[:group]) : self
- group || self
- end
-
- def event_url(options = {})
- option = event_options[:url]
- if option.is_a?(Proc)
- option.call(self).merge(options)
- elsif option.is_a?(Hash)
- option.merge(options)
- elsif option.is_a?(Symbol)
- send(option).merge(options)
- else
- option
- end
- end
-
- # Returns the mail adresses of users that should be notified
- def recipients
- notified = project.notified_users
- notified.reject! {|user| !visible?(user)}
- notified.collect(&:mail)
- end
-
- module ClassMethods
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_list/README b/trustie2/lib/plugins/acts_as_list/README
deleted file mode 100644
index 36ae3188e..000000000
--- a/trustie2/lib/plugins/acts_as_list/README
+++ /dev/null
@@ -1,23 +0,0 @@
-ActsAsList
-==========
-
-This acts_as extension provides the capabilities for sorting and reordering a number of objects in a list. The class that has this specified needs to have a +position+ column defined as an integer on the mapped database table.
-
-
-Example
-=======
-
- class TodoList < ActiveRecord::Base
- has_many :todo_items, :order => "position"
- end
-
- class TodoItem < ActiveRecord::Base
- belongs_to :todo_list
- acts_as_list :scope => :todo_list
- end
-
- todo_list.first.move_to_bottom
- todo_list.last.move_higher
-
-
-Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_list/init.rb b/trustie2/lib/plugins/acts_as_list/init.rb
deleted file mode 100644
index eb87e8790..000000000
--- a/trustie2/lib/plugins/acts_as_list/init.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-$:.unshift "#{File.dirname(__FILE__)}/lib"
-require 'active_record/acts/list'
-ActiveRecord::Base.class_eval { include ActiveRecord::Acts::List }
diff --git a/trustie2/lib/plugins/acts_as_list/lib/active_record/acts/list.rb b/trustie2/lib/plugins/acts_as_list/lib/active_record/acts/list.rb
deleted file mode 100644
index 9361a768c..000000000
--- a/trustie2/lib/plugins/acts_as_list/lib/active_record/acts/list.rb
+++ /dev/null
@@ -1,279 +0,0 @@
-module ActiveRecord
- module Acts #:nodoc:
- module List #:nodoc:
- def self.included(base)
- base.extend(ClassMethods)
- end
-
- # This +acts_as+ extension provides the capabilities for sorting and reordering a number of objects in a list.
- # The class that has this specified needs to have a +position+ column defined as an integer on
- # the mapped database table.
- #
- # Todo list example:
- #
- # class TodoList < ActiveRecord::Base
- # has_many :todo_items, :order => "position"
- # end
- #
- # class TodoItem < ActiveRecord::Base
- # belongs_to :todo_list
- # acts_as_list :scope => :todo_list
- # end
- #
- # todo_list.first.move_to_bottom
- # todo_list.last.move_higher
- module ClassMethods
- # Configuration options are:
- #
- # * +column+ - specifies the column name to use for keeping the position integer (default: +position+)
- # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach _id
- # (if it hasn't already been added) and use that as the foreign key restriction. It's also possible
- # to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.
- # Example: acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'
- def acts_as_list(options = {})
- configuration = { :column => "position", :scope => "1 = 1" }
- configuration.update(options) if options.is_a?(Hash)
-
- configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/
-
- if configuration[:scope].is_a?(Symbol)
- scope_condition_method = %(
- def scope_condition
- if #{configuration[:scope].to_s}.nil?
- "#{configuration[:scope].to_s} IS NULL"
- else
- "#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}"
- end
- end
- )
- else
- scope_condition_method = "def scope_condition() \"#{configuration[:scope]}\" end"
- end
-
- class_eval <<-EOV
- include ActiveRecord::Acts::List::InstanceMethods
-
- def acts_as_list_class
- ::#{self.name}
- end
-
- def position_column
- '#{configuration[:column]}'
- end
-
- #{scope_condition_method}
-
- before_destroy :remove_from_list
- before_create :add_to_list_bottom
- EOV
- end
- end
-
- # All the methods available to a record that has had acts_as_list specified. Each method works
- # by assuming the object to be the item in the list, so chapter.move_lower would move that chapter
- # lower in the list of all chapters. Likewise, chapter.first? would return +true+ if that chapter is
- # the first in the list of all chapters.
- module InstanceMethods
- # Insert the item at the given position (defaults to the top position of 1).
- def insert_at(position = 1)
- insert_at_position(position)
- end
-
- # Swap positions with the next lower item, if one exists.
- def move_lower
- return unless lower_item
-
- acts_as_list_class.transaction do
- lower_item.decrement_position
- increment_position
- end
- end
-
- # Swap positions with the next higher item, if one exists.
- def move_higher
- return unless higher_item
-
- acts_as_list_class.transaction do
- higher_item.increment_position
- decrement_position
- end
- end
-
- # Move to the bottom of the list. If the item is already in the list, the items below it have their
- # position adjusted accordingly.
- def move_to_bottom
- return unless in_list?
- acts_as_list_class.transaction do
- decrement_positions_on_lower_items
- assume_bottom_position
- end
- end
-
- # Move to the top of the list. If the item is already in the list, the items above it have their
- # position adjusted accordingly.
- def move_to_top
- return unless in_list?
- acts_as_list_class.transaction do
- increment_positions_on_higher_items
- assume_top_position
- end
- end
-
- # Move to the given position
- def move_to=(pos)
- case pos.to_s
- when 'highest'
- move_to_top
- when 'higher'
- move_higher
- when 'lower'
- move_lower
- when 'lowest'
- move_to_bottom
- end
- reset_positions_in_list
- end
-
- def reset_positions_in_list
- acts_as_list_class.where(scope_condition).reorder("#{position_column} ASC, id ASC").each_with_index do |item, i|
- unless item.send(position_column) == (i + 1)
- acts_as_list_class.update_all({position_column => (i + 1)}, {:id => item.id})
- end
- end
- end
-
- # Removes the item from the list.
- def remove_from_list
- if in_list?
- decrement_positions_on_lower_items
- update_attribute position_column, nil
- end
- end
-
- # Increase the position of this item without adjusting the rest of the list.
- def increment_position
- return unless in_list?
- update_attribute position_column, self.send(position_column).to_i + 1
- end
-
- # Decrease the position of this item without adjusting the rest of the list.
- def decrement_position
- return unless in_list?
- update_attribute position_column, self.send(position_column).to_i - 1
- end
-
- # Return +true+ if this object is the first in the list.
- def first?
- return false unless in_list?
- self.send(position_column) == 1
- end
-
- # Return +true+ if this object is the last in the list.
- def last?
- return false unless in_list?
- self.send(position_column) == bottom_position_in_list
- end
-
- # Return the next higher item in the list.
- def higher_item
- return nil unless in_list?
- acts_as_list_class.where(
- "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
- ).first
- end
-
- # Return the next lower item in the list.
- def lower_item
- return nil unless in_list?
- acts_as_list_class.where(
- "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
- ).first
- end
-
- # Test if this record is in a list
- def in_list?
- !send(position_column).nil?
- end
-
- private
- def add_to_list_top
- increment_positions_on_all_items
- end
-
- def add_to_list_bottom
- self[position_column] = bottom_position_in_list.to_i + 1
- end
-
- # Overwrite this method to define the scope of the list changes
- def scope_condition() "1" end
-
- # Returns the bottom position number in the list.
- # bottom_position_in_list # => 2
- def bottom_position_in_list(except = nil)
- item = bottom_item(except)
- item ? item.send(position_column) : 0
- end
-
- # Returns the bottom item
- def bottom_item(except = nil)
- conditions = scope_condition
- conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
- acts_as_list_class.where(conditions).reorder("#{position_column} DESC").first
- end
-
- # Forces item to assume the bottom position in the list.
- def assume_bottom_position
- update_attribute(position_column, bottom_position_in_list(self).to_i + 1)
- end
-
- # Forces item to assume the top position in the list.
- def assume_top_position
- update_attribute(position_column, 1)
- end
-
- # This has the effect of moving all the higher items up one.
- def decrement_positions_on_higher_items(position)
- acts_as_list_class.update_all(
- "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} <= #{position}"
- )
- end
-
- # This has the effect of moving all the lower items up one.
- def decrement_positions_on_lower_items
- return unless in_list?
- acts_as_list_class.update_all(
- "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}"
- )
- end
-
- # This has the effect of moving all the higher items down one.
- def increment_positions_on_higher_items
- return unless in_list?
- acts_as_list_class.update_all(
- "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}"
- )
- end
-
- # This has the effect of moving all the lower items down one.
- def increment_positions_on_lower_items(position)
- acts_as_list_class.update_all(
- "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} >= #{position}"
- )
- end
-
- # Increments position (position_column) of all items in the list.
- def increment_positions_on_all_items
- acts_as_list_class.update_all(
- "#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
- )
- end
-
- def insert_at_position(position)
- remove_from_list
- increment_positions_on_lower_items(position)
- self.update_attribute(position_column, position)
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_list/test/list_test.rb b/trustie2/lib/plugins/acts_as_list/test/list_test.rb
deleted file mode 100644
index e89cb8e12..000000000
--- a/trustie2/lib/plugins/acts_as_list/test/list_test.rb
+++ /dev/null
@@ -1,332 +0,0 @@
-require 'test/unit'
-
-require 'rubygems'
-gem 'activerecord', '>= 1.15.4.7794'
-require 'active_record'
-
-require "#{File.dirname(__FILE__)}/../init"
-
-ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
-
-def setup_db
- ActiveRecord::Schema.define(:version => 1) do
- create_table :mixins do |t|
- t.column :pos, :integer
- t.column :parent_id, :integer
- t.column :created_at, :datetime
- t.column :updated_at, :datetime
- end
- end
-end
-
-def teardown_db
- ActiveRecord::Base.connection.tables.each do |table|
- ActiveRecord::Base.connection.drop_table(table)
- end
-end
-
-class Mixin < ActiveRecord::Base
-end
-
-class ListMixin < Mixin
- acts_as_list :column => "pos", :scope => :parent
-
- def self.table_name() "mixins" end
-end
-
-class ListMixinSub1 < ListMixin
-end
-
-class ListMixinSub2 < ListMixin
-end
-
-class ListWithStringScopeMixin < ActiveRecord::Base
- acts_as_list :column => "pos", :scope => 'parent_id = #{parent_id}'
-
- def self.table_name() "mixins" end
-end
-
-
-class ListTest < Test::Unit::TestCase
-
- def setup
- setup_db
- (1..4).each { |counter| ListMixin.create! :pos => counter, :parent_id => 5 }
- end
-
- def teardown
- teardown_db
- end
-
- def test_reordering
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- ListMixin.find(2).move_lower
- assert_equal [1, 3, 2, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- ListMixin.find(2).move_higher
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- ListMixin.find(1).move_to_bottom
- assert_equal [2, 3, 4, 1], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- ListMixin.find(1).move_to_top
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- ListMixin.find(2).move_to_bottom
- assert_equal [1, 3, 4, 2], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- ListMixin.find(4).move_to_top
- assert_equal [4, 1, 3, 2], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
- end
-
- def test_move_to_bottom_with_next_to_last_item
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
- ListMixin.find(3).move_to_bottom
- assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
- end
-
- def test_next_prev
- assert_equal ListMixin.find(2), ListMixin.find(1).lower_item
- assert_nil ListMixin.find(1).higher_item
- assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
- assert_nil ListMixin.find(4).lower_item
- end
-
- def test_injection
- item = ListMixin.new(:parent_id => 1)
- assert_equal "parent_id = 1", item.scope_condition
- assert_equal "pos", item.position_column
- end
-
- def test_insert
- new = ListMixin.create(:parent_id => 20)
- assert_equal 1, new.pos
- assert new.first?
- assert new.last?
-
- new = ListMixin.create(:parent_id => 20)
- assert_equal 2, new.pos
- assert !new.first?
- assert new.last?
-
- new = ListMixin.create(:parent_id => 20)
- assert_equal 3, new.pos
- assert !new.first?
- assert new.last?
-
- new = ListMixin.create(:parent_id => 0)
- assert_equal 1, new.pos
- assert new.first?
- assert new.last?
- end
-
- def test_insert_at
- new = ListMixin.create(:parent_id => 20)
- assert_equal 1, new.pos
-
- new = ListMixin.create(:parent_id => 20)
- assert_equal 2, new.pos
-
- new = ListMixin.create(:parent_id => 20)
- assert_equal 3, new.pos
-
- new4 = ListMixin.create(:parent_id => 20)
- assert_equal 4, new4.pos
-
- new4.insert_at(3)
- assert_equal 3, new4.pos
-
- new.reload
- assert_equal 4, new.pos
-
- new.insert_at(2)
- assert_equal 2, new.pos
-
- new4.reload
- assert_equal 4, new4.pos
-
- new5 = ListMixin.create(:parent_id => 20)
- assert_equal 5, new5.pos
-
- new5.insert_at(1)
- assert_equal 1, new5.pos
-
- new4.reload
- assert_equal 5, new4.pos
- end
-
- def test_delete_middle
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- ListMixin.find(2).destroy
-
- assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- assert_equal 1, ListMixin.find(1).pos
- assert_equal 2, ListMixin.find(3).pos
- assert_equal 3, ListMixin.find(4).pos
-
- ListMixin.find(1).destroy
-
- assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- assert_equal 1, ListMixin.find(3).pos
- assert_equal 2, ListMixin.find(4).pos
- end
-
- def test_with_string_based_scope
- new = ListWithStringScopeMixin.create(:parent_id => 500)
- assert_equal 1, new.pos
- assert new.first?
- assert new.last?
- end
-
- def test_nil_scope
- new1, new2, new3 = ListMixin.create, ListMixin.create, ListMixin.create
- new2.move_higher
- assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
- end
-
-
- def test_remove_from_list_should_then_fail_in_list?
- assert_equal true, ListMixin.find(1).in_list?
- ListMixin.find(1).remove_from_list
- assert_equal false, ListMixin.find(1).in_list?
- end
-
- def test_remove_from_list_should_set_position_to_nil
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- ListMixin.find(2).remove_from_list
-
- assert_equal [2, 1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- assert_equal 1, ListMixin.find(1).pos
- assert_equal nil, ListMixin.find(2).pos
- assert_equal 2, ListMixin.find(3).pos
- assert_equal 3, ListMixin.find(4).pos
- end
-
- def test_remove_before_destroy_does_not_shift_lower_items_twice
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- ListMixin.find(2).remove_from_list
- ListMixin.find(2).destroy
-
- assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
-
- assert_equal 1, ListMixin.find(1).pos
- assert_equal 2, ListMixin.find(3).pos
- assert_equal 3, ListMixin.find(4).pos
- end
-
-end
-
-class ListSubTest < Test::Unit::TestCase
-
- def setup
- setup_db
- (1..4).each { |i| ((i % 2 == 1) ? ListMixinSub1 : ListMixinSub2).create! :pos => i, :parent_id => 5000 }
- end
-
- def teardown
- teardown_db
- end
-
- def test_reordering
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
-
- ListMixin.find(2).move_lower
- assert_equal [1, 3, 2, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
-
- ListMixin.find(2).move_higher
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
-
- ListMixin.find(1).move_to_bottom
- assert_equal [2, 3, 4, 1], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
-
- ListMixin.find(1).move_to_top
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
-
- ListMixin.find(2).move_to_bottom
- assert_equal [1, 3, 4, 2], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
-
- ListMixin.find(4).move_to_top
- assert_equal [4, 1, 3, 2], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
- end
-
- def test_move_to_bottom_with_next_to_last_item
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
- ListMixin.find(3).move_to_bottom
- assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
- end
-
- def test_next_prev
- assert_equal ListMixin.find(2), ListMixin.find(1).lower_item
- assert_nil ListMixin.find(1).higher_item
- assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
- assert_nil ListMixin.find(4).lower_item
- end
-
- def test_injection
- item = ListMixin.new("parent_id"=>1)
- assert_equal "parent_id = 1", item.scope_condition
- assert_equal "pos", item.position_column
- end
-
- def test_insert_at
- new = ListMixin.create("parent_id" => 20)
- assert_equal 1, new.pos
-
- new = ListMixinSub1.create("parent_id" => 20)
- assert_equal 2, new.pos
-
- new = ListMixinSub2.create("parent_id" => 20)
- assert_equal 3, new.pos
-
- new4 = ListMixin.create("parent_id" => 20)
- assert_equal 4, new4.pos
-
- new4.insert_at(3)
- assert_equal 3, new4.pos
-
- new.reload
- assert_equal 4, new.pos
-
- new.insert_at(2)
- assert_equal 2, new.pos
-
- new4.reload
- assert_equal 4, new4.pos
-
- new5 = ListMixinSub1.create("parent_id" => 20)
- assert_equal 5, new5.pos
-
- new5.insert_at(1)
- assert_equal 1, new5.pos
-
- new4.reload
- assert_equal 5, new4.pos
- end
-
- def test_delete_middle
- assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
-
- ListMixin.find(2).destroy
-
- assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
-
- assert_equal 1, ListMixin.find(1).pos
- assert_equal 2, ListMixin.find(3).pos
- assert_equal 3, ListMixin.find(4).pos
-
- ListMixin.find(1).destroy
-
- assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
-
- assert_equal 1, ListMixin.find(3).pos
- assert_equal 2, ListMixin.find(4).pos
- end
-
-end
diff --git a/trustie2/lib/plugins/acts_as_searchable/init.rb b/trustie2/lib/plugins/acts_as_searchable/init.rb
deleted file mode 100644
index 063721756..000000000
--- a/trustie2/lib/plugins/acts_as_searchable/init.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require File.dirname(__FILE__) + '/lib/acts_as_searchable'
-ActiveRecord::Base.send(:include, Redmine::Acts::Searchable)
diff --git a/trustie2/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb b/trustie2/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb
deleted file mode 100644
index 5a1f36752..000000000
--- a/trustie2/lib/plugins/acts_as_searchable/lib/acts_as_searchable.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Acts
- module Searchable
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- # Options:
- # * :columns - a column or an array of columns to search
- # * :project_key - project foreign key (default to project_id)
- # * :date_column - name of the datetime column (default to created_on)
- # * :sort_order - name of the column used to sort results (default to :date_column or created_on)
- # * :permission - permission required to search the model (default to :view_"objects")
- def acts_as_searchable(options = {})
- return if self.included_modules.include?(Redmine::Acts::Searchable::InstanceMethods)
-
- cattr_accessor :searchable_options
- self.searchable_options = options
-
- if searchable_options[:columns].nil?
- raise 'No searchable column defined.'
- elsif !searchable_options[:columns].is_a?(Array)
- searchable_options[:columns] = [] << searchable_options[:columns]
- end
-
- searchable_options[:project_key] ||= "#{table_name}.project_id"
- searchable_options[:date_column] ||= "#{table_name}.created_on"
- searchable_options[:order_column] ||= searchable_options[:date_column]
-
- # Should we search custom fields on this model ?
- searchable_options[:search_custom_fields] = !reflect_on_association(:custom_values).nil?
-
- send :include, Redmine::Acts::Searchable::InstanceMethods
- end
- end
-
- module InstanceMethods
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- # Searches the model for the given tokens
- # projects argument can be either nil (will search all projects), a project or an array of projects
- # Returns the results and the results count
- def search(tokens, projects=nil, options={})
- if projects.is_a?(Array) && projects.empty?
- # no results
- return [[], 0]
- end
-
- # TODO: make user an argument
- user = User.current
- tokens = [] << tokens unless tokens.is_a?(Array)
- projects = [] << projects unless projects.nil? || projects.is_a?(Array)
-
- limit_options = {}
- limit_options[:limit] = options[:limit] if options[:limit]
-
- columns = searchable_options[:columns]
- columns = columns[0..0] if options[:titles_only]
-
- token_clauses = columns.collect {|column| "(LOWER(#{column}) LIKE ?)"}
-
- if !options[:titles_only] && searchable_options[:search_custom_fields]
- searchable_custom_field_ids = CustomField.where(:type => "#{self.name}CustomField", :searchable => true).pluck(:id)
- if searchable_custom_field_ids.any?
- custom_field_sql = "#{table_name}.id IN (SELECT customized_id FROM #{CustomValue.table_name}" +
- " WHERE customized_type='#{self.name}' AND customized_id=#{table_name}.id AND LOWER(value) LIKE ?" +
- " AND #{CustomValue.table_name}.custom_field_id IN (#{searchable_custom_field_ids.join(',')}))"
- token_clauses << custom_field_sql
- end
- end
-
- sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(options[:all_words] ? ' AND ' : ' OR ')
-
- tokens_conditions = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort]
-
- scope = self.scoped
- project_conditions = []
- if searchable_options.has_key?(:permission)
- project_conditions << Project.allowed_to_condition(user, searchable_options[:permission] || :view_project)
- elsif respond_to?(:visible)
- scope = scope.visible(user)
- else
- ActiveSupport::Deprecation.warn "acts_as_searchable with implicit :permission option is deprecated. Add a visible scope to the #{self.name} model or use explicit :permission option."
- project_conditions << Project.allowed_to_condition(user, "view_#{self.name.underscore.pluralize}".to_sym)
- end
- # TODO: use visible scope options instead
- project_conditions << "#{searchable_options[:project_key]} IN (#{projects.collect(&:id).join(',')})" unless projects.nil?
- project_conditions = project_conditions.empty? ? nil : project_conditions.join(' AND ')
-
- results = []
- results_count = 0
-
- scope = scope.
- includes(searchable_options[:include]).
- order("#{searchable_options[:order_column]} " + (options[:before] ? 'DESC' : 'ASC')).
- where(project_conditions).
- where(tokens_conditions)
-
- results_count = scope.count
-
- scope_with_limit = scope.limit(options[:limit])
- if options[:offset]
- scope_with_limit = scope_with_limit.where("#{searchable_options[:date_column]} #{options[:before] ? '<' : '>'} ?", options[:offset])
- end
- results = scope_with_limit.all
-
- [results, results_count]
- end
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_tree/README b/trustie2/lib/plugins/acts_as_tree/README
deleted file mode 100644
index a6cc6a904..000000000
--- a/trustie2/lib/plugins/acts_as_tree/README
+++ /dev/null
@@ -1,26 +0,0 @@
-acts_as_tree
-============
-
-Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children
-association. This requires that you have a foreign key column, which by default is called +parent_id+.
-
- class Category < ActiveRecord::Base
- acts_as_tree :order => "name"
- end
-
- Example:
- root
- \_ child1
- \_ subchild1
- \_ subchild2
-
- root = Category.create("name" => "root")
- child1 = root.children.create("name" => "child1")
- subchild1 = child1.children.create("name" => "subchild1")
-
- root.parent # => nil
- child1.parent # => root
- root.children # => [child1]
- root.children.first.children.first # => subchild1
-
-Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_tree/Rakefile b/trustie2/lib/plugins/acts_as_tree/Rakefile
deleted file mode 100644
index da091d9dd..000000000
--- a/trustie2/lib/plugins/acts_as_tree/Rakefile
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'rake'
-require 'rake/testtask'
-require 'rake/rdoctask'
-
-desc 'Default: run unit tests.'
-task :default => :test
-
-desc 'Test acts_as_tree plugin.'
-Rake::TestTask.new(:test) do |t|
- t.libs << 'lib'
- t.pattern = 'test/**/*_test.rb'
- t.verbose = true
-end
-
-desc 'Generate documentation for acts_as_tree plugin.'
-Rake::RDocTask.new(:rdoc) do |rdoc|
- rdoc.rdoc_dir = 'rdoc'
- rdoc.title = 'acts_as_tree'
- rdoc.options << '--line-numbers' << '--inline-source'
- rdoc.rdoc_files.include('README')
- rdoc.rdoc_files.include('lib/**/*.rb')
-end
diff --git a/trustie2/lib/plugins/acts_as_tree/init.rb b/trustie2/lib/plugins/acts_as_tree/init.rb
deleted file mode 100644
index 0901ddb4a..000000000
--- a/trustie2/lib/plugins/acts_as_tree/init.rb
+++ /dev/null
@@ -1 +0,0 @@
-ActiveRecord::Base.send :include, ActiveRecord::Acts::Tree
diff --git a/trustie2/lib/plugins/acts_as_tree/lib/active_record/acts/tree.rb b/trustie2/lib/plugins/acts_as_tree/lib/active_record/acts/tree.rb
deleted file mode 100644
index d069da972..000000000
--- a/trustie2/lib/plugins/acts_as_tree/lib/active_record/acts/tree.rb
+++ /dev/null
@@ -1,107 +0,0 @@
-module ActiveRecord
- module Acts
- module Tree
- def self.included(base)
- base.extend(ClassMethods)
- end
-
- # Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children
- # association. This requires that you have a foreign key column, which by default is called +parent_id+.
- #
- # class Category < ActiveRecord::Base
- # acts_as_tree :order => "name"
- # end
- #
- # Example:
- # root
- # \_ child1
- # \_ subchild1
- # \_ subchild2
- #
- # root = Category.create("name" => "root")
- # child1 = root.children.create("name" => "child1")
- # subchild1 = child1.children.create("name" => "subchild1")
- #
- # root.parent # => nil
- # child1.parent # => root
- # root.children # => [child1]
- # root.children.first.children.first # => subchild1
- #
- # In addition to the parent and children associations, the following instance methods are added to the class
- # after calling acts_as_tree:
- # * siblings - Returns all the children of the parent, excluding the current node ([subchild2] when called on subchild1)
- # * self_and_siblings - Returns all the children of the parent, including the current node ([subchild1, subchild2] when called on subchild1)
- # * ancestors - Returns all the ancestors of the current node ([child1, root] when called on subchild2)
- # * root - Returns the root of the current node (root when called on subchild2)
- module ClassMethods
- # Configuration options are:
- #
- # * foreign_key - specifies the column name to use for tracking of the tree (default: +parent_id+)
- # * order - makes it possible to sort the children according to this SQL snippet.
- # * counter_cache - keeps a count in a +children_count+ column if set to +true+ (default: +false+).
- def acts_as_tree(options = {})
- configuration = { :foreign_key => "parent_id", :dependent => :destroy, :order => nil, :counter_cache => nil }
- configuration.update(options) if options.is_a?(Hash)
-
- belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache]
- has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => configuration[:dependent]
-
- scope :roots, where("#{configuration[:foreign_key]} IS NULL").order(configuration[:order])
-
- send :include, ActiveRecord::Acts::Tree::InstanceMethods
- end
- end
-
- module InstanceMethods
- # Returns list of ancestors, starting from parent until root.
- #
- # subchild1.ancestors # => [child1, root]
- def ancestors
- node, nodes = self, []
- nodes << node = node.parent while node.parent
- nodes
- end
-
- # Returns list of descendants.
- #
- # root.descendants # => [child1, subchild1, subchild2]
- def descendants(depth=nil)
- depth ||= 0
- result = children.dup
- unless depth == 1
- result += children.collect {|child| child.descendants(depth-1)}.flatten
- end
- result
- end
-
- # Returns list of descendants and a reference to the current node.
- #
- # root.self_and_descendants # => [root, child1, subchild1, subchild2]
- def self_and_descendants(depth=nil)
- [self] + descendants(depth)
- end
-
- # Returns the root node of the tree.
- def root
- node = self
- node = node.parent while node.parent
- node
- end
-
- # Returns all siblings of the current node.
- #
- # subchild1.siblings # => [subchild2]
- def siblings
- self_and_siblings - [self]
- end
-
- # Returns all siblings and a reference to the current node.
- #
- # subchild1.self_and_siblings # => [subchild1, subchild2]
- def self_and_siblings
- parent ? parent.children : self.class.roots
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_tree/test/abstract_unit.rb b/trustie2/lib/plugins/acts_as_tree/test/abstract_unit.rb
deleted file mode 100644
index e69de29bb..000000000
diff --git a/trustie2/lib/plugins/acts_as_tree/test/acts_as_tree_test.rb b/trustie2/lib/plugins/acts_as_tree/test/acts_as_tree_test.rb
deleted file mode 100644
index 018c58e1f..000000000
--- a/trustie2/lib/plugins/acts_as_tree/test/acts_as_tree_test.rb
+++ /dev/null
@@ -1,219 +0,0 @@
-require 'test/unit'
-
-require 'rubygems'
-require 'active_record'
-
-$:.unshift File.dirname(__FILE__) + '/../lib'
-require File.dirname(__FILE__) + '/../init'
-
-class Test::Unit::TestCase
- def assert_queries(num = 1)
- $query_count = 0
- yield
- ensure
- assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed."
- end
-
- def assert_no_queries(&block)
- assert_queries(0, &block)
- end
-end
-
-ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
-
-# AR keeps printing annoying schema statements
-$stdout = StringIO.new
-
-def setup_db
- ActiveRecord::Base.logger
- ActiveRecord::Schema.define(:version => 1) do
- create_table :mixins do |t|
- t.column :type, :string
- t.column :parent_id, :integer
- end
- end
-end
-
-def teardown_db
- ActiveRecord::Base.connection.tables.each do |table|
- ActiveRecord::Base.connection.drop_table(table)
- end
-end
-
-class Mixin < ActiveRecord::Base
-end
-
-class TreeMixin < Mixin
- acts_as_tree :foreign_key => "parent_id", :order => "id"
-end
-
-class TreeMixinWithoutOrder < Mixin
- acts_as_tree :foreign_key => "parent_id"
-end
-
-class RecursivelyCascadedTreeMixin < Mixin
- acts_as_tree :foreign_key => "parent_id"
- has_one :first_child, :class_name => 'RecursivelyCascadedTreeMixin', :foreign_key => :parent_id
-end
-
-class TreeTest < Test::Unit::TestCase
-
- def setup
- setup_db
- @root1 = TreeMixin.create!
- @root_child1 = TreeMixin.create! :parent_id => @root1.id
- @child1_child = TreeMixin.create! :parent_id => @root_child1.id
- @root_child2 = TreeMixin.create! :parent_id => @root1.id
- @root2 = TreeMixin.create!
- @root3 = TreeMixin.create!
- end
-
- def teardown
- teardown_db
- end
-
- def test_children
- assert_equal @root1.children, [@root_child1, @root_child2]
- assert_equal @root_child1.children, [@child1_child]
- assert_equal @child1_child.children, []
- assert_equal @root_child2.children, []
- end
-
- def test_parent
- assert_equal @root_child1.parent, @root1
- assert_equal @root_child1.parent, @root_child2.parent
- assert_nil @root1.parent
- end
-
- def test_delete
- assert_equal 6, TreeMixin.count
- @root1.destroy
- assert_equal 2, TreeMixin.count
- @root2.destroy
- @root3.destroy
- assert_equal 0, TreeMixin.count
- end
-
- def test_insert
- @extra = @root1.children.create
-
- assert @extra
-
- assert_equal @extra.parent, @root1
-
- assert_equal 3, @root1.children.size
- assert @root1.children.include?(@extra)
- assert @root1.children.include?(@root_child1)
- assert @root1.children.include?(@root_child2)
- end
-
- def test_ancestors
- assert_equal [], @root1.ancestors
- assert_equal [@root1], @root_child1.ancestors
- assert_equal [@root_child1, @root1], @child1_child.ancestors
- assert_equal [@root1], @root_child2.ancestors
- assert_equal [], @root2.ancestors
- assert_equal [], @root3.ancestors
- end
-
- def test_root
- assert_equal @root1, TreeMixin.root
- assert_equal @root1, @root1.root
- assert_equal @root1, @root_child1.root
- assert_equal @root1, @child1_child.root
- assert_equal @root1, @root_child2.root
- assert_equal @root2, @root2.root
- assert_equal @root3, @root3.root
- end
-
- def test_roots
- assert_equal [@root1, @root2, @root3], TreeMixin.roots
- end
-
- def test_siblings
- assert_equal [@root2, @root3], @root1.siblings
- assert_equal [@root_child2], @root_child1.siblings
- assert_equal [], @child1_child.siblings
- assert_equal [@root_child1], @root_child2.siblings
- assert_equal [@root1, @root3], @root2.siblings
- assert_equal [@root1, @root2], @root3.siblings
- end
-
- def test_self_and_siblings
- assert_equal [@root1, @root2, @root3], @root1.self_and_siblings
- assert_equal [@root_child1, @root_child2], @root_child1.self_and_siblings
- assert_equal [@child1_child], @child1_child.self_and_siblings
- assert_equal [@root_child1, @root_child2], @root_child2.self_and_siblings
- assert_equal [@root1, @root2, @root3], @root2.self_and_siblings
- assert_equal [@root1, @root2, @root3], @root3.self_and_siblings
- end
-end
-
-class TreeTestWithEagerLoading < Test::Unit::TestCase
-
- def setup
- teardown_db
- setup_db
- @root1 = TreeMixin.create!
- @root_child1 = TreeMixin.create! :parent_id => @root1.id
- @child1_child = TreeMixin.create! :parent_id => @root_child1.id
- @root_child2 = TreeMixin.create! :parent_id => @root1.id
- @root2 = TreeMixin.create!
- @root3 = TreeMixin.create!
-
- @rc1 = RecursivelyCascadedTreeMixin.create!
- @rc2 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc1.id
- @rc3 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc2.id
- @rc4 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc3.id
- end
-
- def teardown
- teardown_db
- end
-
- def test_eager_association_loading
- roots = TreeMixin.find(:all, :include => :children, :conditions => "mixins.parent_id IS NULL", :order => "mixins.id")
- assert_equal [@root1, @root2, @root3], roots
- assert_no_queries do
- assert_equal 2, roots[0].children.size
- assert_equal 0, roots[1].children.size
- assert_equal 0, roots[2].children.size
- end
- end
-
- def test_eager_association_loading_with_recursive_cascading_three_levels_has_many
- root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :children => { :children => :children } }, :order => 'mixins.id')
- assert_equal @rc4, assert_no_queries { root_node.children.first.children.first.children.first }
- end
-
- def test_eager_association_loading_with_recursive_cascading_three_levels_has_one
- root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :first_child => { :first_child => :first_child } }, :order => 'mixins.id')
- assert_equal @rc4, assert_no_queries { root_node.first_child.first_child.first_child }
- end
-
- def test_eager_association_loading_with_recursive_cascading_three_levels_belongs_to
- leaf_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :parent => { :parent => :parent } }, :order => 'mixins.id DESC')
- assert_equal @rc1, assert_no_queries { leaf_node.parent.parent.parent }
- end
-end
-
-class TreeTestWithoutOrder < Test::Unit::TestCase
-
- def setup
- setup_db
- @root1 = TreeMixinWithoutOrder.create!
- @root2 = TreeMixinWithoutOrder.create!
- end
-
- def teardown
- teardown_db
- end
-
- def test_root
- assert [@root1, @root2].include?(TreeMixinWithoutOrder.root)
- end
-
- def test_roots
- assert_equal [], [@root1, @root2] - TreeMixinWithoutOrder.roots
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_tree/test/database.yml b/trustie2/lib/plugins/acts_as_tree/test/database.yml
deleted file mode 100644
index e69de29bb..000000000
diff --git a/trustie2/lib/plugins/acts_as_tree/test/fixtures/mixin.rb b/trustie2/lib/plugins/acts_as_tree/test/fixtures/mixin.rb
deleted file mode 100644
index e69de29bb..000000000
diff --git a/trustie2/lib/plugins/acts_as_tree/test/fixtures/mixins.yml b/trustie2/lib/plugins/acts_as_tree/test/fixtures/mixins.yml
deleted file mode 100644
index e69de29bb..000000000
diff --git a/trustie2/lib/plugins/acts_as_tree/test/schema.rb b/trustie2/lib/plugins/acts_as_tree/test/schema.rb
deleted file mode 100644
index e69de29bb..000000000
diff --git a/trustie2/lib/plugins/acts_as_versioned/CHANGELOG b/trustie2/lib/plugins/acts_as_versioned/CHANGELOG
deleted file mode 100644
index a5d339cc7..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/CHANGELOG
+++ /dev/null
@@ -1,74 +0,0 @@
-*SVN* (version numbers are overrated)
-
-* (5 Oct 2006) Allow customization of #versions association options [Dan Peterson]
-
-*0.5.1*
-
-* (8 Aug 2006) Versioned models now belong to the unversioned model. @article_version.article.class => Article [Aslak Hellesoy]
-
-*0.5* # do versions even matter for plugins?
-
-* (21 Apr 2006) Added without_locking and without_revision methods.
-
- Foo.without_revision do
- @foo.update_attributes ...
- end
-
-*0.4*
-
-* (28 March 2006) Rename non_versioned_fields to non_versioned_columns (old one is kept for compatibility).
-* (28 March 2006) Made explicit documentation note that string column names are required for non_versioned_columns.
-
-*0.3.1*
-
-* (7 Jan 2006) explicitly set :foreign_key option for the versioned model's belongs_to assocation for STI [Caged]
-* (7 Jan 2006) added tests to prove has_many :through joins work
-
-*0.3*
-
-* (2 Jan 2006) added ability to share a mixin with versioned class
-* (2 Jan 2006) changed the dynamic version model to MyModel::Version
-
-*0.2.4*
-
-* (27 Nov 2005) added note about possible destructive behavior of if_changed? [Michael Schuerig]
-
-*0.2.3*
-
-* (12 Nov 2005) fixed bug with old behavior of #blank? [Michael Schuerig]
-* (12 Nov 2005) updated tests to use ActiveRecord Schema
-
-*0.2.2*
-
-* (3 Nov 2005) added documentation note to #acts_as_versioned [Martin Jul]
-
-*0.2.1*
-
-* (6 Oct 2005) renamed dirty? to changed? to keep it uniform. it was aliased to keep it backwards compatible.
-
-*0.2*
-
-* (6 Oct 2005) added find_versions and find_version class methods.
-
-* (6 Oct 2005) removed transaction from create_versioned_table().
- this way you can specify your own transaction around a group of operations.
-
-* (30 Sep 2005) fixed bug where find_versions() would order by 'version' twice. (found by Joe Clark)
-
-* (26 Sep 2005) added :sequence_name option to acts_as_versioned to set the sequence name on the versioned model
-
-*0.1.3* (18 Sep 2005)
-
-* First RubyForge release
-
-*0.1.2*
-
-* check if module is already included when acts_as_versioned is called
-
-*0.1.1*
-
-* Adding tests and rdocs
-
-*0.1*
-
-* Initial transfer from Rails ticket: http://dev.rubyonrails.com/ticket/1974
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/MIT-LICENSE b/trustie2/lib/plugins/acts_as_versioned/MIT-LICENSE
deleted file mode 100644
index 9f0d419b5..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/MIT-LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2005 Rick Olson
-
-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, title 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.
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/README b/trustie2/lib/plugins/acts_as_versioned/README
deleted file mode 100644
index 8961f0522..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/README
+++ /dev/null
@@ -1,28 +0,0 @@
-= acts_as_versioned
-
-This library adds simple versioning to an ActiveRecord module. ActiveRecord is required.
-
-== Resources
-
-Install
-
-* gem install acts_as_versioned
-
-Rubyforge project
-
-* http://rubyforge.org/projects/ar-versioned
-
-RDocs
-
-* http://ar-versioned.rubyforge.org
-
-Subversion
-
-* http://techno-weenie.net/svn/projects/acts_as_versioned
-
-Collaboa
-
-* http://collaboa.techno-weenie.net/repository/browse/acts_as_versioned
-
-Special thanks to Dreamer on ##rubyonrails for help in early testing. His ServerSideWiki (http://serversidewiki.com)
-was the first project to use acts_as_versioned in the wild.
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/RUNNING_UNIT_TESTS b/trustie2/lib/plugins/acts_as_versioned/RUNNING_UNIT_TESTS
deleted file mode 100644
index a6e55b841..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/RUNNING_UNIT_TESTS
+++ /dev/null
@@ -1,41 +0,0 @@
-== Creating the test database
-
-The default name for the test databases is "activerecord_versioned". If you
-want to use another database name then be sure to update the connection
-adapter setups you want to test with in test/connections//connection.rb.
-When you have the database online, you can import the fixture tables with
-the test/fixtures/db_definitions/*.sql files.
-
-Make sure that you create database objects with the same user that you specified in i
-connection.rb otherwise (on Postgres, at least) tests for default values will fail.
-
-== Running with Rake
-
-The easiest way to run the unit tests is through Rake. The default task runs
-the entire test suite for all the adapters. You can also run the suite on just
-one adapter by using the tasks test_mysql_ruby, test_ruby_mysql, test_sqlite,
-or test_postresql. For more information, checkout the full array of rake tasks with "rake -T"
-
-Rake can be found at http://rake.rubyforge.org
-
-== Running by hand
-
-Unit tests are located in test directory. If you only want to run a single test suite,
-or don't want to bother with Rake, you can do so with something like:
-
- cd test; ruby -I "connections/native_mysql" base_test.rb
-
-That'll run the base suite using the MySQL-Ruby adapter. Change the adapter
-and test suite name as needed.
-
-== Faster tests
-
-If you are using a database that supports transactions, you can set the
-"AR_TX_FIXTURES" environment variable to "yes" to use transactional fixtures.
-This gives a very large speed boost. With rake:
-
- rake AR_TX_FIXTURES=yes
-
-Or, by hand:
-
- AR_TX_FIXTURES=yes ruby -I connections/native_sqlite3 base_test.rb
diff --git a/trustie2/lib/plugins/acts_as_versioned/Rakefile b/trustie2/lib/plugins/acts_as_versioned/Rakefile
deleted file mode 100644
index 3ae69e961..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/Rakefile
+++ /dev/null
@@ -1,182 +0,0 @@
-require 'rubygems'
-
-Gem::manage_gems
-
-require 'rake/rdoctask'
-require 'rake/packagetask'
-require 'rake/gempackagetask'
-require 'rake/testtask'
-require 'rake/contrib/rubyforgepublisher'
-
-PKG_NAME = 'acts_as_versioned'
-PKG_VERSION = '0.3.1'
-PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
-PROD_HOST = "technoweenie@bidwell.textdrive.com"
-RUBY_FORGE_PROJECT = 'ar-versioned'
-RUBY_FORGE_USER = 'technoweenie'
-
-desc 'Default: run unit tests.'
-task :default => :test
-
-desc 'Test the calculations plugin.'
-Rake::TestTask.new(:test) do |t|
- t.libs << 'lib'
- t.pattern = 'test/**/*_test.rb'
- t.verbose = true
-end
-
-desc 'Generate documentation for the calculations plugin.'
-Rake::RDocTask.new(:rdoc) do |rdoc|
- rdoc.rdoc_dir = 'rdoc'
- rdoc.title = "#{PKG_NAME} -- Simple versioning with active record models"
- rdoc.options << '--line-numbers --inline-source'
- rdoc.rdoc_files.include('README', 'CHANGELOG', 'RUNNING_UNIT_TESTS')
- rdoc.rdoc_files.include('lib/**/*.rb')
-end
-
-spec = Gem::Specification.new do |s|
- s.name = PKG_NAME
- s.version = PKG_VERSION
- s.platform = Gem::Platform::RUBY
- s.summary = "Simple versioning with active record models"
- s.files = FileList["{lib,test}/**/*"].to_a + %w(README MIT-LICENSE CHANGELOG RUNNING_UNIT_TESTS)
- s.files.delete "acts_as_versioned_plugin.sqlite.db"
- s.files.delete "acts_as_versioned_plugin.sqlite3.db"
- s.files.delete "test/debug.log"
- s.require_path = 'lib'
- s.autorequire = 'acts_as_versioned'
- s.has_rdoc = true
- s.test_files = Dir['test/**/*_test.rb']
- s.add_dependency 'activerecord', '>= 1.10.1'
- s.add_dependency 'activesupport', '>= 1.1.1'
- s.author = "Rick Olson"
- s.email = "technoweenie@gmail.com"
- s.homepage = "http://techno-weenie.net"
-end
-
-Rake::GemPackageTask.new(spec) do |pkg|
- pkg.need_tar = true
-end
-
-desc "Publish the API documentation"
-task :pdoc => [:rdoc] do
- Rake::RubyForgePublisher.new(RUBY_FORGE_PROJECT, RUBY_FORGE_USER).upload
-end
-
-desc 'Publish the gem and API docs'
-task :publish => [:pdoc, :rubyforge_upload]
-
-desc "Publish the release files to RubyForge."
-task :rubyforge_upload => :package do
- files = %w(gem tgz).map { |ext| "pkg/#{PKG_FILE_NAME}.#{ext}" }
-
- if RUBY_FORGE_PROJECT then
- require 'net/http'
- require 'open-uri'
-
- project_uri = "http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/"
- project_data = open(project_uri) { |data| data.read }
- group_id = project_data[/[?&]group_id=(\d+)/, 1]
- raise "Couldn't get group id" unless group_id
-
- # This echos password to shell which is a bit sucky
- if ENV["RUBY_FORGE_PASSWORD"]
- password = ENV["RUBY_FORGE_PASSWORD"]
- else
- print "#{RUBY_FORGE_USER}@rubyforge.org's password: "
- password = STDIN.gets.chomp
- end
-
- login_response = Net::HTTP.start("rubyforge.org", 80) do |http|
- data = [
- "login=1",
- "form_loginname=#{RUBY_FORGE_USER}",
- "form_pw=#{password}"
- ].join("&")
- http.post("/account/login.php", data)
- end
-
- cookie = login_response["set-cookie"]
- raise "Login failed" unless cookie
- headers = { "Cookie" => cookie }
-
- release_uri = "http://rubyforge.org/frs/admin/?group_id=#{group_id}"
- release_data = open(release_uri, headers) { |data| data.read }
- package_id = release_data[/[?&]package_id=(\d+)/, 1]
- raise "Couldn't get package id" unless package_id
-
- first_file = true
- release_id = ""
-
- files.each do |filename|
- basename = File.basename(filename)
- file_ext = File.extname(filename)
- file_data = File.open(filename, "rb") { |file| file.read }
-
- puts "Releasing #{basename}..."
-
- release_response = Net::HTTP.start("rubyforge.org", 80) do |http|
- release_date = Time.now.strftime("%Y-%m-%d %H:%M")
- type_map = {
- ".zip" => "3000",
- ".tgz" => "3110",
- ".gz" => "3110",
- ".gem" => "1400"
- }; type_map.default = "9999"
- type = type_map[file_ext]
- boundary = "rubyqMY6QN9bp6e4kS21H4y0zxcvoor"
-
- query_hash = if first_file then
- {
- "group_id" => group_id,
- "package_id" => package_id,
- "release_name" => PKG_FILE_NAME,
- "release_date" => release_date,
- "type_id" => type,
- "processor_id" => "8000", # Any
- "release_notes" => "",
- "release_changes" => "",
- "preformatted" => "1",
- "submit" => "1"
- }
- else
- {
- "group_id" => group_id,
- "release_id" => release_id,
- "package_id" => package_id,
- "step2" => "1",
- "type_id" => type,
- "processor_id" => "8000", # Any
- "submit" => "Add This File"
- }
- end
-
- query = "?" + query_hash.map do |(name, value)|
- [name, URI.encode(value)].join("=")
- end.join("&")
-
- data = [
- "--" + boundary,
- "Content-Disposition: form-data; name=\"userfile\"; filename=\"#{basename}\"",
- "Content-Type: application/octet-stream",
- "Content-Transfer-Encoding: binary",
- "", file_data, ""
- ].join("\x0D\x0A")
-
- release_headers = headers.merge(
- "Content-Type" => "multipart/form-data; boundary=#{boundary}"
- )
-
- target = first_file ? "/frs/admin/qrs.php" : "/frs/admin/editrelease.php"
- http.post(target + query, data, release_headers)
- end
-
- if first_file then
- release_id = release_response.body[/release_id=(\d+)/, 1]
- raise("Couldn't get release id") unless release_id
- end
-
- first_file = false
- end
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/init.rb b/trustie2/lib/plugins/acts_as_versioned/init.rb
deleted file mode 100644
index 5937bbc7c..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/init.rb
+++ /dev/null
@@ -1 +0,0 @@
-require 'acts_as_versioned'
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/lib/acts_as_versioned.rb b/trustie2/lib/plugins/acts_as_versioned/lib/acts_as_versioned.rb
deleted file mode 100644
index ad38dabb7..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/lib/acts_as_versioned.rb
+++ /dev/null
@@ -1,568 +0,0 @@
-# Copyright (c) 2005 Rick Olson
-#
-# 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, title 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.
-
-module ActiveRecord #:nodoc:
- module Acts #:nodoc:
- # Specify this act if you want to save a copy of the row in a versioned table. This assumes there is a
- # versioned table ready and that your model has a version field. This works with optimistic locking if the lock_version
- # column is present as well.
- #
- # The class for the versioned model is derived the first time it is seen. Therefore, if you change your database schema you have to restart
- # your container for the changes to be reflected. In development mode this usually means restarting WEBrick.
- #
- # class Page < ActiveRecord::Base
- # # assumes pages_versions table
- # acts_as_versioned
- # end
- #
- # Example:
- #
- # page = Page.create(:title => 'hello world!')
- # page.version # => 1
- #
- # page.title = 'hello world'
- # page.save
- # page.version # => 2
- # page.versions.size # => 2
- #
- # page.revert_to(1) # using version number
- # page.title # => 'hello world!'
- #
- # page.revert_to(page.versions.last) # using versioned instance
- # page.title # => 'hello world'
- #
- # page.versions.earliest # efficient query to find the first version
- # page.versions.latest # efficient query to find the most recently created version
- #
- #
- # Simple Queries to page between versions
- #
- # page.versions.before(version)
- # page.versions.after(version)
- #
- # Access the previous/next versions from the versioned model itself
- #
- # version = page.versions.latest
- # version.previous # go back one version
- # version.next # go forward one version
- #
- # See ActiveRecord::Acts::Versioned::ClassMethods#acts_as_versioned for configuration options
- module Versioned
- CALLBACKS = [:set_new_version, :save_version_on_create, :save_version?, :clear_altered_attributes]
- def self.included(base) # :nodoc:
- base.extend ClassMethods
- end
-
- module ClassMethods
- # == Configuration options
- #
- # * class_name - versioned model class name (default: PageVersion in the above example)
- # * table_name - versioned model table name (default: page_versions in the above example)
- # * foreign_key - foreign key used to relate the versioned model to the original model (default: page_id in the above example)
- # * inheritance_column - name of the column to save the model's inheritance_column value for STI. (default: versioned_type)
- # * version_column - name of the column in the model that keeps the version number (default: version)
- # * sequence_name - name of the custom sequence to be used by the versioned model.
- # * limit - number of revisions to keep, defaults to unlimited
- # * if - symbol of method to check before saving a new version. If this method returns false, a new version is not saved.
- # For finer control, pass either a Proc or modify Model#version_condition_met?
- #
- # acts_as_versioned :if => Proc.new { |auction| !auction.expired? }
- #
- # or...
- #
- # class Auction
- # def version_condition_met? # totally bypasses the :if option
- # !expired?
- # end
- # end
- #
- # * if_changed - Simple way of specifying attributes that are required to be changed before saving a model. This takes
- # either a symbol or array of symbols. WARNING - This will attempt to overwrite any attribute setters you may have.
- # Use this instead if you want to write your own attribute setters (and ignore if_changed):
- #
- # def name=(new_name)
- # write_changed_attribute :name, new_name
- # end
- #
- # * extend - Lets you specify a module to be mixed in both the original and versioned models. You can also just pass a block
- # to create an anonymous mixin:
- #
- # class Auction
- # acts_as_versioned do
- # def started?
- # !started_at.nil?
- # end
- # end
- # end
- #
- # or...
- #
- # module AuctionExtension
- # def started?
- # !started_at.nil?
- # end
- # end
- # class Auction
- # acts_as_versioned :extend => AuctionExtension
- # end
- #
- # Example code:
- #
- # @auction = Auction.find(1)
- # @auction.started?
- # @auction.versions.first.started?
- #
- # == Database Schema
- #
- # The model that you're versioning needs to have a 'version' attribute. The model is versioned
- # into a table called #{model}_versions where the model name is singlular. The _versions table should
- # contain all the fields you want versioned, the same version column, and a #{model}_id foreign key field.
- #
- # A lock_version field is also accepted if your model uses Optimistic Locking. If your table uses Single Table inheritance,
- # then that field is reflected in the versioned model as 'versioned_type' by default.
- #
- # Acts_as_versioned comes prepared with the ActiveRecord::Acts::Versioned::ActMethods::ClassMethods#create_versioned_table
- # method, perfect for a migration. It will also create the version column if the main model does not already have it.
- #
- # class AddVersions < ActiveRecord::Migration
- # def self.up
- # # create_versioned_table takes the same options hash
- # # that create_table does
- # Post.create_versioned_table
- # end
- #
- # def self.down
- # Post.drop_versioned_table
- # end
- # end
- #
- # == Changing What Fields Are Versioned
- #
- # By default, acts_as_versioned will version all but these fields:
- #
- # [self.primary_key, inheritance_column, 'version', 'lock_version', versioned_inheritance_column]
- #
- # You can add or change those by modifying #non_versioned_columns. Note that this takes strings and not symbols.
- #
- # class Post < ActiveRecord::Base
- # acts_as_versioned
- # self.non_versioned_columns << 'comments_count'
- # end
- #
- def acts_as_versioned(options = {}, &extension)
- # don't allow multiple calls
- return if self.included_modules.include?(ActiveRecord::Acts::Versioned::ActMethods)
-
- send :include, ActiveRecord::Acts::Versioned::ActMethods
-
- cattr_accessor :versioned_class_name, :versioned_foreign_key, :versioned_table_name, :versioned_inheritance_column,
- :version_column, :max_version_limit, :track_altered_attributes, :version_condition, :version_sequence_name, :non_versioned_columns,
- :version_association_options
-
- # legacy
- alias_method :non_versioned_fields, :non_versioned_columns
- alias_method :non_versioned_fields=, :non_versioned_columns=
-
- class << self
- alias_method :non_versioned_fields, :non_versioned_columns
- alias_method :non_versioned_fields=, :non_versioned_columns=
- end
-
- send :attr_accessor, :altered_attributes
-
- self.versioned_class_name = options[:class_name] || "Version"
- self.versioned_foreign_key = options[:foreign_key] || self.to_s.foreign_key
- self.versioned_table_name = options[:table_name] || "#{table_name_prefix}#{base_class.name.demodulize.underscore}_versions#{table_name_suffix}"
- self.versioned_inheritance_column = options[:inheritance_column] || "versioned_#{inheritance_column}"
- self.version_column = options[:version_column] || 'version'
- self.version_sequence_name = options[:sequence_name]
- self.max_version_limit = options[:limit].to_i
- self.version_condition = options[:if] || true
- self.non_versioned_columns = [self.primary_key, inheritance_column, 'version', 'lock_version', versioned_inheritance_column]
- self.version_association_options = {
- :class_name => "#{self.to_s}::#{versioned_class_name}",
- :foreign_key => versioned_foreign_key,
- :dependent => :delete_all
- }.merge(options[:association_options] || {})
-
- if block_given?
- extension_module_name = "#{versioned_class_name}Extension"
- silence_warnings do
- self.const_set(extension_module_name, Module.new(&extension))
- end
-
- options[:extend] = self.const_get(extension_module_name)
- end
-
- class_eval do
- has_many :versions, version_association_options do
- # finds earliest version of this record
- def earliest
- @earliest ||= order('version').first
- end
-
- # find latest version of this record
- def latest
- @latest ||= order('version desc').first
- end
- end
- before_save :set_new_version
- after_create :save_version_on_create
- after_update :save_version
- after_save :clear_old_versions
- after_save :clear_altered_attributes
-
- unless options[:if_changed].nil?
- self.track_altered_attributes = true
- options[:if_changed] = [options[:if_changed]] unless options[:if_changed].is_a?(Array)
- options[:if_changed].each do |attr_name|
- define_method("#{attr_name}=") do |value|
- write_changed_attribute attr_name, value
- end
- end
- end
-
- include options[:extend] if options[:extend].is_a?(Module)
- end
-
- # create the dynamic versioned model
- const_set(versioned_class_name, Class.new(ActiveRecord::Base)).class_eval do
- def self.reloadable? ; false ; end
- # find first version before the given version
- def self.before(version)
- order('version desc').
- where("#{original_class.versioned_foreign_key} = ? and version < ?", version.send(original_class.versioned_foreign_key), version.version).
- first
- end
-
- # find first version after the given version.
- def self.after(version)
- order('version').
- where("#{original_class.versioned_foreign_key} = ? and version > ?", version.send(original_class.versioned_foreign_key), version.version).
- first
- end
-
- def previous
- self.class.before(self)
- end
-
- def next
- self.class.after(self)
- end
-
- def versions_count
- page.version
- end
- end
-
- versioned_class.cattr_accessor :original_class
- versioned_class.original_class = self
- versioned_class.table_name = versioned_table_name
- versioned_class.belongs_to self.to_s.demodulize.underscore.to_sym,
- :class_name => "::#{self.to_s}",
- :foreign_key => versioned_foreign_key
- versioned_class.send :include, options[:extend] if options[:extend].is_a?(Module)
- versioned_class.set_sequence_name version_sequence_name if version_sequence_name
- end
- end
-
- module ActMethods
- def self.included(base) # :nodoc:
- base.extend ClassMethods
- end
-
- # Finds a specific version of this record
- def find_version(version = nil)
- self.class.find_version(id, version)
- end
-
- # Saves a version of the model if applicable
- def save_version
- save_version_on_create if save_version?
- end
-
- # Saves a version of the model in the versioned table. This is called in the after_save callback by default
- def save_version_on_create
- rev = self.class.versioned_class.new
- self.clone_versioned_model(self, rev)
- rev.version = send(self.class.version_column)
- rev.send("#{self.class.versioned_foreign_key}=", self.id)
- rev.save
- end
-
- # Clears old revisions if a limit is set with the :limit option in acts_as_versioned.
- # Override this method to set your own criteria for clearing old versions.
- def clear_old_versions
- return if self.class.max_version_limit == 0
- excess_baggage = send(self.class.version_column).to_i - self.class.max_version_limit
- if excess_baggage > 0
- sql = "DELETE FROM #{self.class.versioned_table_name} WHERE version <= #{excess_baggage} AND #{self.class.versioned_foreign_key} = #{self.id}"
- self.class.versioned_class.connection.execute sql
- end
- end
-
- def versions_count
- version
- end
-
- # Reverts a model to a given version. Takes either a version number or an instance of the versioned model
- def revert_to(version)
- if version.is_a?(self.class.versioned_class)
- return false unless version.send(self.class.versioned_foreign_key) == self.id and !version.new_record?
- else
- return false unless version = versions.find_by_version(version)
- end
- self.clone_versioned_model(version, self)
- self.send("#{self.class.version_column}=", version.version)
- true
- end
-
- # Reverts a model to a given version and saves the model.
- # Takes either a version number or an instance of the versioned model
- def revert_to!(version)
- revert_to(version) ? save_without_revision : false
- end
-
- # Temporarily turns off Optimistic Locking while saving. Used when reverting so that a new version is not created.
- def save_without_revision
- save_without_revision!
- true
- rescue
- false
- end
-
- def save_without_revision!
- without_locking do
- without_revision do
- save!
- end
- end
- end
-
- # Returns an array of attribute keys that are versioned. See non_versioned_columns
- def versioned_attributes
- self.attributes.keys.select { |k| !self.class.non_versioned_columns.include?(k) }
- end
-
- # If called with no parameters, gets whether the current model has changed and needs to be versioned.
- # If called with a single parameter, gets whether the parameter has changed.
- def changed?(attr_name = nil)
- attr_name.nil? ?
- (!self.class.track_altered_attributes || (altered_attributes && altered_attributes.length > 0)) :
- (altered_attributes && altered_attributes.include?(attr_name.to_s))
- end
-
- # keep old dirty? method
- alias_method :dirty?, :changed?
-
- # Clones a model. Used when saving a new version or reverting a model's version.
- def clone_versioned_model(orig_model, new_model)
- self.versioned_attributes.each do |key|
- new_model.send("#{key}=", orig_model.send(key)) if orig_model.respond_to?(key)
- end
-
- if self.class.columns_hash.include?(self.class.inheritance_column)
- if orig_model.is_a?(self.class.versioned_class)
- new_model[new_model.class.inheritance_column] = orig_model[self.class.versioned_inheritance_column]
- elsif new_model.is_a?(self.class.versioned_class)
- new_model[self.class.versioned_inheritance_column] = orig_model[orig_model.class.inheritance_column]
- end
- end
- end
-
- # Checks whether a new version shall be saved or not. Calls version_condition_met? and changed?.
- def save_version?
- version_condition_met? && changed?
- end
-
- # Checks condition set in the :if option to check whether a revision should be created or not. Override this for
- # custom version condition checking.
- def version_condition_met?
- case
- when version_condition.is_a?(Symbol)
- send(version_condition)
- when version_condition.respond_to?(:call) && (version_condition.arity == 1 || version_condition.arity == -1)
- version_condition.call(self)
- else
- version_condition
- end
- end
-
- # Executes the block with the versioning callbacks disabled.
- #
- # @foo.without_revision do
- # @foo.save
- # end
- #
- def without_revision(&block)
- self.class.without_revision(&block)
- end
-
- # Turns off optimistic locking for the duration of the block
- #
- # @foo.without_locking do
- # @foo.save
- # end
- #
- def without_locking(&block)
- self.class.without_locking(&block)
- end
-
- def empty_callback() end #:nodoc:
-
- protected
- # sets the new version before saving, unless you're using optimistic locking. In that case, let it take care of the version.
- def set_new_version
- self.send("#{self.class.version_column}=", self.next_version) if new_record? || (!locking_enabled? && save_version?)
- end
-
- # Gets the next available version for the current record, or 1 for a new record
- def next_version
- return 1 if new_record?
- (versions.calculate(:max, :version) || 0) + 1
- end
-
- # clears current changed attributes. Called after save.
- def clear_altered_attributes
- self.altered_attributes = []
- end
-
- def write_changed_attribute(attr_name, attr_value)
- # Convert to db type for comparison. Avoids failing Float<=>String comparisons.
- attr_value_for_db = self.class.columns_hash[attr_name.to_s].type_cast(attr_value)
- (self.altered_attributes ||= []) << attr_name.to_s unless self.changed?(attr_name) || self.send(attr_name) == attr_value_for_db
- write_attribute(attr_name, attr_value_for_db)
- end
-
- module ClassMethods
- # Finds a specific version of a specific row of this model
- def find_version(id, version = nil)
- return find(id) unless version
-
- conditions = ["#{versioned_foreign_key} = ? AND version = ?", id, version]
- options = { :conditions => conditions, :limit => 1 }
-
- if result = find_versions(id, options).first
- result
- else
- raise RecordNotFound, "Couldn't find #{name} with ID=#{id} and VERSION=#{version}"
- end
- end
-
- # Finds versions of a specific model. Takes an options hash like find
- def find_versions(id, options = {})
- versioned_class.all({
- :conditions => ["#{versioned_foreign_key} = ?", id],
- :order => 'version' }.merge(options))
- end
-
- # Returns an array of columns that are versioned. See non_versioned_columns
- def versioned_columns
- self.columns.select { |c| !non_versioned_columns.include?(c.name) }
- end
-
- # Returns an instance of the dynamic versioned model
- def versioned_class
- const_get versioned_class_name
- end
-
- # Rake migration task to create the versioned table using options passed to acts_as_versioned
- def create_versioned_table(create_table_options = {})
- # create version column in main table if it does not exist
- if !self.content_columns.find { |c| %w(version lock_version).include? c.name }
- self.connection.add_column table_name, :version, :integer
- end
-
- self.connection.create_table(versioned_table_name, create_table_options) do |t|
- t.column versioned_foreign_key, :integer
- t.column :version, :integer
- end
-
- updated_col = nil
- self.versioned_columns.each do |col|
- updated_col = col if !updated_col && %(updated_at updated_on).include?(col.name)
- self.connection.add_column versioned_table_name, col.name, col.type,
- :limit => col.limit,
- :default => col.default,
- :scale => col.scale,
- :precision => col.precision
- end
-
- if type_col = self.columns_hash[inheritance_column]
- self.connection.add_column versioned_table_name, versioned_inheritance_column, type_col.type,
- :limit => type_col.limit,
- :default => type_col.default,
- :scale => type_col.scale,
- :precision => type_col.precision
- end
-
- if updated_col.nil?
- self.connection.add_column versioned_table_name, :updated_at, :timestamp
- end
- end
-
- # Rake migration task to drop the versioned table
- def drop_versioned_table
- self.connection.drop_table versioned_table_name
- end
-
- # Executes the block with the versioning callbacks disabled.
- #
- # Foo.without_revision do
- # @foo.save
- # end
- #
- def without_revision(&block)
- class_eval do
- CALLBACKS.each do |attr_name|
- alias_method "orig_#{attr_name}".to_sym, attr_name
- alias_method attr_name, :empty_callback
- end
- end
- block.call
- ensure
- class_eval do
- CALLBACKS.each do |attr_name|
- alias_method attr_name, "orig_#{attr_name}".to_sym
- end
- end
- end
-
- # Turns off optimistic locking for the duration of the block
- #
- # Foo.without_locking do
- # @foo.save
- # end
- #
- def without_locking(&block)
- current = ActiveRecord::Base.lock_optimistically
- ActiveRecord::Base.lock_optimistically = false if current
- result = block.call
- ActiveRecord::Base.lock_optimistically = true if current
- result
- end
- end
- end
- end
- end
-end
-
-ActiveRecord::Base.send :include, ActiveRecord::Acts::Versioned
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/abstract_unit.rb b/trustie2/lib/plugins/acts_as_versioned/test/abstract_unit.rb
deleted file mode 100644
index 86f50620c..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/abstract_unit.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-$:.unshift(File.dirname(__FILE__) + '/../../../rails/activesupport/lib')
-$:.unshift(File.dirname(__FILE__) + '/../../../rails/activerecord/lib')
-$:.unshift(File.dirname(__FILE__) + '/../lib')
-require 'test/unit'
-begin
- require 'active_support'
- require 'active_record'
- require 'active_record/fixtures'
-rescue LoadError
- require 'rubygems'
- retry
-end
-require 'acts_as_versioned'
-
-config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
-ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
-ActiveRecord::Base.configurations = {'test' => config[ENV['DB'] || 'sqlite3']}
-ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test'])
-
-load(File.dirname(__FILE__) + "/schema.rb")
-
-# set up custom sequence on widget_versions for DBs that support sequences
-if ENV['DB'] == 'postgresql'
- ActiveRecord::Base.connection.execute "DROP SEQUENCE widgets_seq;" rescue nil
- ActiveRecord::Base.connection.remove_column :widget_versions, :id
- ActiveRecord::Base.connection.execute "CREATE SEQUENCE widgets_seq START 101;"
- ActiveRecord::Base.connection.execute "ALTER TABLE widget_versions ADD COLUMN id INTEGER PRIMARY KEY DEFAULT nextval('widgets_seq');"
-end
-
-Test::Unit::TestCase.fixture_path = File.dirname(__FILE__) + "/fixtures/"
-$:.unshift(Test::Unit::TestCase.fixture_path)
-
-class Test::Unit::TestCase #:nodoc:
- # Turn off transactional fixtures if you're working with MyISAM tables in MySQL
- self.use_transactional_fixtures = true
-
- # Instantiated fixtures are slow, but give you @david where you otherwise would need people(:david)
- self.use_instantiated_fixtures = false
-
- # Add more helper methods to be used by all tests here...
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/database.yml b/trustie2/lib/plugins/acts_as_versioned/test/database.yml
deleted file mode 100644
index 506e6bd37..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/database.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-sqlite:
- :adapter: sqlite
- :dbfile: acts_as_versioned_plugin.sqlite.db
-sqlite3:
- :adapter: sqlite3
- :dbfile: acts_as_versioned_plugin.sqlite3.db
-postgresql:
- :adapter: postgresql
- :username: postgres
- :password: postgres
- :database: acts_as_versioned_plugin_test
- :min_messages: ERROR
-mysql:
- :adapter: mysql
- :host: localhost
- :username: rails
- :password:
- :database: acts_as_versioned_plugin_test
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/debug.log b/trustie2/lib/plugins/acts_as_versioned/test/debug.log
deleted file mode 100644
index 31a569a6a..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/debug.log
+++ /dev/null
@@ -1 +0,0 @@
-# Logfile created on 2017-04-19 11:44:31 +0800 by logger.rb/31641
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/authors.yml b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/authors.yml
deleted file mode 100644
index bd7a5aed6..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/authors.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-caged:
- id: 1
- name: caged
-mly:
- id: 2
- name: mly
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/landmark.rb b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/landmark.rb
deleted file mode 100644
index cb9b93057..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/landmark.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class Landmark < ActiveRecord::Base
- acts_as_versioned :if_changed => [ :name, :longitude, :latitude ]
-end
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/landmark_versions.yml b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/landmark_versions.yml
deleted file mode 100644
index 2dbd54ed2..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/landmark_versions.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-washington:
- id: 1
- landmark_id: 1
- version: 1
- name: Washington, D.C.
- latitude: 38.895
- longitude: -77.036667
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/landmarks.yml b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/landmarks.yml
deleted file mode 100644
index 46d96176a..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/landmarks.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-washington:
- id: 1
- name: Washington, D.C.
- latitude: 38.895
- longitude: -77.036667
- version: 1
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/locked_pages.yml b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/locked_pages.yml
deleted file mode 100644
index 318e776cb..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/locked_pages.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-welcome:
- id: 1
- title: Welcome to the weblog
- lock_version: 24
- type: LockedPage
-thinking:
- id: 2
- title: So I was thinking
- lock_version: 24
- type: SpecialLockedPage
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml
deleted file mode 100644
index 5c978e629..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/locked_pages_revisions.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-welcome_1:
- id: 1
- page_id: 1
- title: Welcome to the weblg
- version: 23
- version_type: LockedPage
-
-welcome_2:
- id: 2
- page_id: 1
- title: Welcome to the weblog
- version: 24
- version_type: LockedPage
-
-thinking_1:
- id: 3
- page_id: 2
- title: So I was thinking!!!
- version: 23
- version_type: SpecialLockedPage
-
-thinking_2:
- id: 4
- page_id: 2
- title: So I was thinking
- version: 24
- version_type: SpecialLockedPage
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb
deleted file mode 100644
index 9512b5e82..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/migrations/1_add_versioned_tables.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class AddVersionedTables < ActiveRecord::Migration
- def self.up
- create_table("things") do |t|
- t.column :title, :text
- end
- Thing.create_versioned_table
- end
-
- def self.down
- Thing.drop_versioned_table
- drop_table "things" rescue nil
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/page.rb b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/page.rb
deleted file mode 100644
index f133e351a..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/page.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-class Page < ActiveRecord::Base
- belongs_to :author
- has_many :authors, :through => :versions, :order => 'name'
- belongs_to :revisor, :class_name => 'Author'
- has_many :revisors, :class_name => 'Author', :through => :versions, :order => 'name'
- acts_as_versioned :if => :feeling_good? do
- def self.included(base)
- base.cattr_accessor :feeling_good
- base.feeling_good = true
- base.belongs_to :author
- base.belongs_to :revisor, :class_name => 'Author'
- end
-
- def feeling_good?
- @@feeling_good == true
- end
- end
-end
-
-module LockedPageExtension
- def hello_world
- 'hello_world'
- end
-end
-
-class LockedPage < ActiveRecord::Base
- acts_as_versioned \
- :inheritance_column => :version_type,
- :foreign_key => :page_id,
- :table_name => :locked_pages_revisions,
- :class_name => 'LockedPageRevision',
- :version_column => :lock_version,
- :limit => 2,
- :if_changed => :title,
- :extend => LockedPageExtension
-end
-
-class SpecialLockedPage < LockedPage
-end
-
-class Author < ActiveRecord::Base
- has_many :pages
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/page_versions.yml b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/page_versions.yml
deleted file mode 100644
index ef565fa4f..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/page_versions.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-welcome_2:
- id: 1
- page_id: 1
- title: Welcome to the weblog
- body: Such a lovely day
- version: 24
- author_id: 1
- revisor_id: 1
-welcome_1:
- id: 2
- page_id: 1
- title: Welcome to the weblg
- body: Such a lovely day
- version: 23
- author_id: 2
- revisor_id: 2
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/pages.yml b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/pages.yml
deleted file mode 100644
index 07ac51f97..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/pages.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-welcome:
- id: 1
- title: Welcome to the weblog
- body: Such a lovely day
- version: 24
- author_id: 1
- revisor_id: 1
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/widget.rb b/trustie2/lib/plugins/acts_as_versioned/test/fixtures/widget.rb
deleted file mode 100644
index 086ac2b40..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/fixtures/widget.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-class Widget < ActiveRecord::Base
- acts_as_versioned :sequence_name => 'widgets_seq', :association_options => {
- :dependent => :nullify, :order => 'version desc'
- }
- non_versioned_columns << 'foo'
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/migration_test.rb b/trustie2/lib/plugins/acts_as_versioned/test/migration_test.rb
deleted file mode 100644
index 4ead4a8fe..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/migration_test.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require File.join(File.dirname(__FILE__), 'abstract_unit')
-
-if ActiveRecord::Base.connection.supports_migrations?
- class Thing < ActiveRecord::Base
- attr_accessor :version
- acts_as_versioned
- end
-
- class MigrationTest < Test::Unit::TestCase
- self.use_transactional_fixtures = false
- def teardown
- if ActiveRecord::Base.connection.respond_to?(:initialize_schema_information)
- ActiveRecord::Base.connection.initialize_schema_information
- ActiveRecord::Base.connection.update "UPDATE schema_info SET version = 0"
- else
- ActiveRecord::Base.connection.initialize_schema_migrations_table
- ActiveRecord::Base.connection.assume_migrated_upto_version(0)
- end
-
- Thing.connection.drop_table "things" rescue nil
- Thing.connection.drop_table "thing_versions" rescue nil
- Thing.reset_column_information
- end
-
- def test_versioned_migration
- assert_raises(ActiveRecord::StatementInvalid) { Thing.create :title => 'blah blah' }
- # take 'er up
- ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/')
- t = Thing.create :title => 'blah blah', :price => 123.45, :type => 'Thing'
- assert_equal 1, t.versions.size
-
- # check that the price column has remembered its value correctly
- assert_equal t.price, t.versions.first.price
- assert_equal t.title, t.versions.first.title
- assert_equal t[:type], t.versions.first[:type]
-
- # make sure that the precision of the price column has been preserved
- assert_equal 7, Thing::Version.columns.find{|c| c.name == "price"}.precision
- assert_equal 2, Thing::Version.columns.find{|c| c.name == "price"}.scale
-
- # now lets take 'er back down
- ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/')
- assert_raises(ActiveRecord::StatementInvalid) { Thing.create :title => 'blah blah' }
- end
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/schema.rb b/trustie2/lib/plugins/acts_as_versioned/test/schema.rb
deleted file mode 100644
index 7d5153d07..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/schema.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-ActiveRecord::Schema.define(:version => 0) do
- create_table :pages, :force => true do |t|
- t.column :version, :integer
- t.column :title, :string, :limit => 255
- t.column :body, :text
- t.column :updated_on, :datetime
- t.column :author_id, :integer
- t.column :revisor_id, :integer
- end
-
- create_table :page_versions, :force => true do |t|
- t.column :page_id, :integer
- t.column :version, :integer
- t.column :title, :string, :limit => 255
- t.column :body, :text
- t.column :updated_on, :datetime
- t.column :author_id, :integer
- t.column :revisor_id, :integer
- end
-
- create_table :authors, :force => true do |t|
- t.column :page_id, :integer
- t.column :name, :string
- end
-
- create_table :locked_pages, :force => true do |t|
- t.column :lock_version, :integer
- t.column :title, :string, :limit => 255
- t.column :type, :string, :limit => 255
- end
-
- create_table :locked_pages_revisions, :force => true do |t|
- t.column :page_id, :integer
- t.column :version, :integer
- t.column :title, :string, :limit => 255
- t.column :version_type, :string, :limit => 255
- t.column :updated_at, :datetime
- end
-
- create_table :widgets, :force => true do |t|
- t.column :name, :string, :limit => 50
- t.column :foo, :string
- t.column :version, :integer
- t.column :updated_at, :datetime
- end
-
- create_table :widget_versions, :force => true do |t|
- t.column :widget_id, :integer
- t.column :name, :string, :limit => 50
- t.column :version, :integer
- t.column :updated_at, :datetime
- end
-
- create_table :landmarks, :force => true do |t|
- t.column :name, :string
- t.column :latitude, :float
- t.column :longitude, :float
- t.column :version, :integer
- end
-
- create_table :landmark_versions, :force => true do |t|
- t.column :landmark_id, :integer
- t.column :name, :string
- t.column :latitude, :float
- t.column :longitude, :float
- t.column :version, :integer
- end
-end
diff --git a/trustie2/lib/plugins/acts_as_versioned/test/versioned_test.rb b/trustie2/lib/plugins/acts_as_versioned/test/versioned_test.rb
deleted file mode 100644
index a7bc2082b..000000000
--- a/trustie2/lib/plugins/acts_as_versioned/test/versioned_test.rb
+++ /dev/null
@@ -1,347 +0,0 @@
-require File.join(File.dirname(__FILE__), 'abstract_unit')
-require File.join(File.dirname(__FILE__), 'fixtures/page')
-require File.join(File.dirname(__FILE__), 'fixtures/widget')
-
-class VersionedTest < Test::Unit::TestCase
- fixtures :pages, :page_versions, :locked_pages, :locked_pages_revisions, :authors, :landmarks, :landmark_versions
- set_fixture_class :page_versions => Page::Version
-
- def test_saves_versioned_copy
- p = Page.create! :title => 'first title', :body => 'first body'
- assert !p.new_record?
- assert_equal 1, p.versions.size
- assert_equal 1, p.version
- assert_instance_of Page.versioned_class, p.versions.first
- end
-
- def test_saves_without_revision
- p = pages(:welcome)
- old_versions = p.versions.count
-
- p.save_without_revision
-
- p.without_revision do
- p.update_attributes :title => 'changed'
- end
-
- assert_equal old_versions, p.versions.count
- end
-
- def test_rollback_with_version_number
- p = pages(:welcome)
- assert_equal 24, p.version
- assert_equal 'Welcome to the weblog', p.title
-
- assert p.revert_to!(p.versions.first.version), "Couldn't revert to 23"
- assert_equal 23, p.version
- assert_equal 'Welcome to the weblg', p.title
- end
-
- def test_versioned_class_name
- assert_equal 'Version', Page.versioned_class_name
- assert_equal 'LockedPageRevision', LockedPage.versioned_class_name
- end
-
- def test_versioned_class
- assert_equal Page::Version, Page.versioned_class
- assert_equal LockedPage::LockedPageRevision, LockedPage.versioned_class
- end
-
- def test_special_methods
- assert_nothing_raised { pages(:welcome).feeling_good? }
- assert_nothing_raised { pages(:welcome).versions.first.feeling_good? }
- assert_nothing_raised { locked_pages(:welcome).hello_world }
- assert_nothing_raised { locked_pages(:welcome).versions.first.hello_world }
- end
-
- def test_rollback_with_version_class
- p = pages(:welcome)
- assert_equal 24, p.version
- assert_equal 'Welcome to the weblog', p.title
-
- assert p.revert_to!(p.versions.first), "Couldn't revert to 23"
- assert_equal 23, p.version
- assert_equal 'Welcome to the weblg', p.title
- end
-
- def test_rollback_fails_with_invalid_revision
- p = locked_pages(:welcome)
- assert !p.revert_to!(locked_pages(:thinking))
- end
-
- def test_saves_versioned_copy_with_options
- p = LockedPage.create! :title => 'first title'
- assert !p.new_record?
- assert_equal 1, p.versions.size
- assert_instance_of LockedPage.versioned_class, p.versions.first
- end
-
- def test_rollback_with_version_number_with_options
- p = locked_pages(:welcome)
- assert_equal 'Welcome to the weblog', p.title
- assert_equal 'LockedPage', p.versions.first.version_type
-
- assert p.revert_to!(p.versions.first.version), "Couldn't revert to 23"
- assert_equal 'Welcome to the weblg', p.title
- assert_equal 'LockedPage', p.versions.first.version_type
- end
-
- def test_rollback_with_version_class_with_options
- p = locked_pages(:welcome)
- assert_equal 'Welcome to the weblog', p.title
- assert_equal 'LockedPage', p.versions.first.version_type
-
- assert p.revert_to!(p.versions.first), "Couldn't revert to 1"
- assert_equal 'Welcome to the weblg', p.title
- assert_equal 'LockedPage', p.versions.first.version_type
- end
-
- def test_saves_versioned_copy_with_sti
- p = SpecialLockedPage.create! :title => 'first title'
- assert !p.new_record?
- assert_equal 1, p.versions.size
- assert_instance_of LockedPage.versioned_class, p.versions.first
- assert_equal 'SpecialLockedPage', p.versions.first.version_type
- end
-
- def test_rollback_with_version_number_with_sti
- p = locked_pages(:thinking)
- assert_equal 'So I was thinking', p.title
-
- assert p.revert_to!(p.versions.first.version), "Couldn't revert to 1"
- assert_equal 'So I was thinking!!!', p.title
- assert_equal 'SpecialLockedPage', p.versions.first.version_type
- end
-
- def test_lock_version_works_with_versioning
- p = locked_pages(:thinking)
- p2 = LockedPage.find(p.id)
-
- p.title = 'fresh title'
- p.save
- assert_equal 2, p.versions.size # limit!
-
- assert_raises(ActiveRecord::StaleObjectError) do
- p2.title = 'stale title'
- p2.save
- end
- end
-
- def test_version_if_condition
- p = Page.create! :title => "title"
- assert_equal 1, p.version
-
- Page.feeling_good = false
- p.save
- assert_equal 1, p.version
- Page.feeling_good = true
- end
-
- def test_version_if_condition2
- # set new if condition
- Page.class_eval do
- def new_feeling_good() title[0..0] == 'a'; end
- alias_method :old_feeling_good, :feeling_good?
- alias_method :feeling_good?, :new_feeling_good
- end
-
- p = Page.create! :title => "title"
- assert_equal 1, p.version # version does not increment
- assert_equal 1, p.versions(true).size
-
- p.update_attributes(:title => 'new title')
- assert_equal 1, p.version # version does not increment
- assert_equal 1, p.versions(true).size
-
- p.update_attributes(:title => 'a title')
- assert_equal 2, p.version
- assert_equal 2, p.versions(true).size
-
- # reset original if condition
- Page.class_eval { alias_method :feeling_good?, :old_feeling_good }
- end
-
- def test_version_if_condition_with_block
- # set new if condition
- old_condition = Page.version_condition
- Page.version_condition = Proc.new { |page| page.title[0..0] == 'b' }
-
- p = Page.create! :title => "title"
- assert_equal 1, p.version # version does not increment
- assert_equal 1, p.versions(true).size
-
- p.update_attributes(:title => 'a title')
- assert_equal 1, p.version # version does not increment
- assert_equal 1, p.versions(true).size
-
- p.update_attributes(:title => 'b title')
- assert_equal 2, p.version
- assert_equal 2, p.versions(true).size
-
- # reset original if condition
- Page.version_condition = old_condition
- end
-
- def test_version_no_limit
- p = Page.create! :title => "title", :body => 'first body'
- p.save
- p.save
- 5.times do |i|
- assert_page_title p, i
- end
- end
-
- def test_version_max_limit
- p = LockedPage.create! :title => "title"
- p.update_attributes(:title => "title1")
- p.update_attributes(:title => "title2")
- 5.times do |i|
- assert_page_title p, i, :lock_version
- assert p.versions(true).size <= 2, "locked version can only store 2 versions"
- end
- end
-
- def test_track_altered_attributes_default_value
- assert !Page.track_altered_attributes
- assert LockedPage.track_altered_attributes
- assert SpecialLockedPage.track_altered_attributes
- end
-
- def test_version_order
- assert_equal 23, pages(:welcome).versions.first.version
- assert_equal 24, pages(:welcome).versions.last.version
- end
-
- def test_track_altered_attributes
- p = LockedPage.create! :title => "title"
- assert_equal 1, p.lock_version
- assert_equal 1, p.versions(true).size
-
- p.title = 'title'
- assert !p.save_version?
- p.save
- assert_equal 2, p.lock_version # still increments version because of optimistic locking
- assert_equal 1, p.versions(true).size
-
- p.title = 'updated title'
- assert p.save_version?
- p.save
- assert_equal 3, p.lock_version
- assert_equal 1, p.versions(true).size # version 1 deleted
-
- p.title = 'updated title!'
- assert p.save_version?
- p.save
- assert_equal 4, p.lock_version
- assert_equal 2, p.versions(true).size # version 1 deleted
- end
-
- def assert_page_title(p, i, version_field = :version)
- p.title = "title#{i}"
- p.save
- assert_equal "title#{i}", p.title
- assert_equal (i+4), p.send(version_field)
- end
-
- def test_find_versions
- assert_equal 2, locked_pages(:welcome).versions.size
- assert_equal 1, locked_pages(:welcome).versions.find(:all, :conditions => ['title LIKE ?', '%weblog%']).length
- assert_equal 2, locked_pages(:welcome).versions.find(:all, :conditions => ['title LIKE ?', '%web%']).length
- assert_equal 0, locked_pages(:thinking).versions.find(:all, :conditions => ['title LIKE ?', '%web%']).length
- assert_equal 2, locked_pages(:welcome).versions.length
- end
-
- def test_find_version
- assert_equal page_versions(:welcome_1), Page.find_version(pages(:welcome).id, 23)
- assert_equal page_versions(:welcome_2), Page.find_version(pages(:welcome).id, 24)
- assert_equal pages(:welcome), Page.find_version(pages(:welcome).id)
-
- assert_equal page_versions(:welcome_1), pages(:welcome).find_version(23)
- assert_equal page_versions(:welcome_2), pages(:welcome).find_version(24)
- assert_equal pages(:welcome), pages(:welcome).find_version
-
- assert_raise(ActiveRecord::RecordNotFound) { Page.find_version(pages(:welcome).id, 1) }
- assert_raise(ActiveRecord::RecordNotFound) { Page.find_version(0, 23) }
- end
-
- def test_with_sequence
- assert_equal 'widgets_seq', Widget.versioned_class.sequence_name
- 3.times { Widget.create! :name => 'new widget' }
- assert_equal 3, Widget.count
- assert_equal 3, Widget.versioned_class.count
- end
-
- def test_has_many_through
- assert_equal [authors(:caged), authors(:mly)], pages(:welcome).authors
- end
-
- def test_has_many_through_with_custom_association
- assert_equal [authors(:caged), authors(:mly)], pages(:welcome).revisors
- end
-
- def test_referential_integrity
- pages(:welcome).destroy
- assert_equal 0, Page.count
- assert_equal 0, Page::Version.count
- end
-
- def test_association_options
- association = Page.reflect_on_association(:versions)
- options = association.options
- assert_equal :delete_all, options[:dependent]
- assert_equal 'version', options[:order]
-
- association = Widget.reflect_on_association(:versions)
- options = association.options
- assert_equal :nullify, options[:dependent]
- assert_equal 'version desc', options[:order]
- assert_equal 'widget_id', options[:foreign_key]
-
- widget = Widget.create! :name => 'new widget'
- assert_equal 1, Widget.count
- assert_equal 1, Widget.versioned_class.count
- widget.destroy
- assert_equal 0, Widget.count
- assert_equal 1, Widget.versioned_class.count
- end
-
- def test_versioned_records_should_belong_to_parent
- page = pages(:welcome)
- page_version = page.versions.last
- assert_equal page, page_version.page
- end
-
- def test_unaltered_attributes
- landmarks(:washington).attributes = landmarks(:washington).attributes.except("id")
- assert !landmarks(:washington).changed?
- end
-
- def test_unchanged_string_attributes
- landmarks(:washington).attributes = landmarks(:washington).attributes.except("id").inject({}) { |params, (key, value)| params.update(key => value.to_s) }
- assert !landmarks(:washington).changed?
- end
-
- def test_should_find_earliest_version
- assert_equal page_versions(:welcome_1), pages(:welcome).versions.earliest
- end
-
- def test_should_find_latest_version
- assert_equal page_versions(:welcome_2), pages(:welcome).versions.latest
- end
-
- def test_should_find_previous_version
- assert_equal page_versions(:welcome_1), page_versions(:welcome_2).previous
- assert_equal page_versions(:welcome_1), pages(:welcome).versions.before(page_versions(:welcome_2))
- end
-
- def test_should_find_next_version
- assert_equal page_versions(:welcome_2), page_versions(:welcome_1).next
- assert_equal page_versions(:welcome_2), pages(:welcome).versions.after(page_versions(:welcome_1))
- end
-
- def test_should_find_version_count
- assert_equal 24, pages(:welcome).versions_count
- assert_equal 24, page_versions(:welcome_1).versions_count
- assert_equal 24, page_versions(:welcome_2).versions_count
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/acts_as_watchable/init.rb b/trustie2/lib/plugins/acts_as_watchable/init.rb
deleted file mode 100644
index f39cc7d18..000000000
--- a/trustie2/lib/plugins/acts_as_watchable/init.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# Include hook code here
-require File.dirname(__FILE__) + '/lib/acts_as_watchable'
-ActiveRecord::Base.send(:include, Redmine::Acts::Watchable)
diff --git a/trustie2/lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb b/trustie2/lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb
deleted file mode 100644
index 36a230462..000000000
--- a/trustie2/lib/plugins/acts_as_watchable/lib/acts_as_watchable.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# ActsAsWatchable
-module Redmine
- module Acts
- module Watchable
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- def acts_as_watchable(options = {})
- return if self.included_modules.include?(Redmine::Acts::Watchable::InstanceMethods)
- class_eval do
- has_many :watchers, :as => :watchable, :dependent => :delete_all
- has_many :watcher_users, :through => :watchers, :source => :user, :validate => false
-
- scope :watched_by, lambda { |user_id|
- { :include => :watchers,
- :conditions => ["#{Watcher.table_name}.user_id = ?", user_id] }
- }
- attr_protected :watcher_ids, :watcher_user_ids
- end
- send :include, Redmine::Acts::Watchable::InstanceMethods
- alias_method_chain :watcher_user_ids=, :uniq_ids
- end
- end
-
- module InstanceMethods
- def self.included(base)
- base.extend ClassMethods
- end
-
- # Returns an array of users that are proposed as watchers
- def addable_watcher_users
- users = self.project.users.sort - self.watcher_users
- if respond_to?(:visible?)
- users.reject! {|user| !visible?(user)}
- end
- users
- end
-
- # Adds user as a watcher
- def add_watcher(user)
- self.watchers << Watcher.new(:user => user)
- end
-
- # Removes user from the watchers list
- ################### modified by liuping
- def remove_watcher(user)
- return nil unless user && user.is_a?(User)
- if self.instance_of?(User)
- Watcher.delete_all "watchable_type = 'Principal' AND watchable_id = #{self.id} AND user_id = #{user.id}"
- else
- Watcher.delete_all "watchable_type = '#{self.class}' AND watchable_id = #{self.id} AND user_id = #{user.id}"
- end
- end
-
- # Adds/removes watcher
- def set_watcher(user, watching=true)
- watching ? add_watcher(user) : remove_watcher(user)
- end
-
- # Overrides watcher_user_ids= to make user_ids uniq
- def watcher_user_ids_with_uniq_ids=(user_ids)
- if user_ids.is_a?(Array)
- user_ids = user_ids.uniq
- end
- send :watcher_user_ids_without_uniq_ids=, user_ids
- end
-
- # Returns true if object is watched by +user+
- def watched_by?(user)
- !!(user && self.watcher_user_ids.detect {|uid| uid == user.id })
- end
-
- def notified_watchers
- notified = watcher_users.active
- notified.reject! {|user| user.mail.blank? || user.mail_notification == 'none'}
- if respond_to?(:visible?)
- notified.reject! {|user| !visible?(user)}
- end
- notified
- end
-
- # Returns an array of watchers' email addresses
- def watcher_recipients
- notified_watchers.collect(&:mail)
- end
-
- module ClassMethods; end
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/.autotest b/trustie2/lib/plugins/awesome_nested_set/.autotest
deleted file mode 100644
index 54518a40a..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/.autotest
+++ /dev/null
@@ -1,13 +0,0 @@
-Autotest.add_hook :initialize do |at|
- at.clear_mappings
-
- at.add_mapping %r%^lib/(.*)\.rb$% do |_, m|
- at.files_matching %r%^test/#{m[1]}_test.rb$%
- end
-
- at.add_mapping(%r%^test/.*\.rb$%) {|filename, _| filename }
-
- at.add_mapping %r%^test/fixtures/(.*)s.yml% do |_, _|
- at.files_matching %r%^test/.*\.rb$%
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/.travis.yml b/trustie2/lib/plugins/awesome_nested_set/.travis.yml
deleted file mode 100644
index 179e88bdf..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/.travis.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-notifications:
- email:
- - parndt@gmail.com
-env:
- - DB=sqlite3
- - DB=sqlite3mem
- - DB=postgresql
- - DB=mysql
-rvm:
- - 1.8.7
- - 1.9.2
- - 1.9.3
- - rbx-2.0
- - jruby
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/CHANGELOG b/trustie2/lib/plugins/awesome_nested_set/CHANGELOG
deleted file mode 100644
index 140164fcf..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/CHANGELOG
+++ /dev/null
@@ -1,14 +0,0 @@
-2.0.2
-* Fixed deprecation warning under Rails 3.1 [Philip Arndt]
-* Converted Test::Unit matchers to RSpec. [Uģis Ozols]
-* Added inverse_of to associations to improve performance rendering trees. [Sergio Cambra]
-* Added row locking and fixed some race conditions. [Markus J. Q. Roberts]
-
-2.0.1
-* Fixed a bug with move_to not using nested_set_scope [Andreas Sekine]
-
-2.0.0.pre
-* Expect Rails 3
-* Changed how callbacks work. Returning false in a before_move action does not block save operations. Use a validation or exception in the callback if you need that.
-* Switched to RSpec
-* Remove use of Comparable
diff --git a/trustie2/lib/plugins/awesome_nested_set/MIT-LICENSE b/trustie2/lib/plugins/awesome_nested_set/MIT-LICENSE
deleted file mode 100644
index d05b828de..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/MIT-LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2007-2011 Collective Idea
-
-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, title 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.
diff --git a/trustie2/lib/plugins/awesome_nested_set/README.rdoc b/trustie2/lib/plugins/awesome_nested_set/README.rdoc
deleted file mode 100644
index 6a7380b60..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/README.rdoc
+++ /dev/null
@@ -1,100 +0,0 @@
-= AwesomeNestedSet
-
-Awesome Nested Set is an implementation of the nested set pattern for ActiveRecord models. It is replacement for acts_as_nested_set and BetterNestedSet, but more awesome.
-
-Version 2 supports Rails 3. Gem versions prior to 2.0 support Rails 2.
-
-== What makes this so awesome?
-
-This is a new implementation of nested set based off of BetterNestedSet that fixes some bugs, removes tons of duplication, adds a few useful methods, and adds STI support.
-
-== Installation
-
- Add to your Gemfile:
-
- gem 'awesome_nested_set'
-
-== Usage
-
-To make use of awesome_nested_set, your model needs to have 3 fields: lft, rgt, and parent_id:
-
- class CreateCategories < ActiveRecord::Migration
- def self.up
- create_table :categories do |t|
- t.string :name
- t.integer :parent_id
- t.integer :lft
- t.integer :rgt
- end
- end
-
- def self.down
- drop_table :categories
- end
- end
-
-Enable the nested set functionality by declaring acts_as_nested_set on your model
-
- class Category < ActiveRecord::Base
- acts_as_nested_set
- end
-
-Run `rake rdoc` to generate the API docs and see CollectiveIdea::Acts::NestedSet for more info.
-
-== Protecting attributes from mass assignment
-
-It's generally best to "white list" the attributes that can be used in mass assignment:
-
- class Category < ActiveRecord::Base
- acts_as_nested_set
- attr_accessible :name, :parent_id
- end
-
-If for some reason that is not possible, you will probably want to protect the lft and rgt attributes:
-
- class Category < ActiveRecord::Base
- acts_as_nested_set
- attr_protected :lft, :rgt
- end
-
-== Conversion from other trees
-
-Coming from acts_as_tree or another system where you only have a parent_id? No problem. Simply add the lft & rgt fields as above, and then run
-
- Category.rebuild!
-
-Your tree will be converted to a valid nested set. Awesome!
-
-== View Helper
-
-The view helper is called #nested_set_options.
-
-Example usage:
-
- <%= f.select :parent_id, nested_set_options(Category, @category) {|i| "#{'-' * i.level} #{i.name}" } %>
-
- <%= select_tag 'parent_id', options_for_select(nested_set_options(Category) {|i| "#{'-' * i.level} #{i.name}" } ) %>
-
-See CollectiveIdea::Acts::NestedSet::Helper for more information about the helpers.
-
-== References
-
-You can learn more about nested sets at: http://threebit.net/tutorials/nestedset/tutorial1.html
-
-== How to contribute
-
-If you find what you might think is a bug:
-
-1. Check the GitHub issue tracker to see if anyone else has had the same issue.
- http://github.com/collectiveidea/awesome_nested_set/issues/
-2. If you don't see anything, create an issue with information on how to reproduce it.
-
-If you want to contribute an enhancement or a fix:
-
-1. Fork the project on github.
- http://github.com/collectiveidea/awesome_nested_set/
-2. Make your changes with tests.
-3. Commit the changes without making changes to the Rakefile, VERSION, or any other files that aren't related to your enhancement or fix
-4. Send a pull request.
-
-Copyright ©2008 Collective Idea, released under the MIT license
diff --git a/trustie2/lib/plugins/awesome_nested_set/Rakefile b/trustie2/lib/plugins/awesome_nested_set/Rakefile
deleted file mode 100644
index b913bc5e2..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/Rakefile
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- encoding: utf-8 -*-
-$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
-require 'rubygems'
-require 'bundler/setup'
-require 'awesome_nested_set/version'
-
-require "rspec/core/rake_task"
-RSpec::Core::RakeTask.new(:spec)
-
-task :default => :spec
-
-task :build do
- system "gem build awesome_nested_set.gemspec"
-end
-
-task :release => :build do
- system "gem push awesome_nested_set-#{ActsAsGeocodable::VERSION}.gem"
-end
-
-require 'rdoc/task'
-desc 'Generate documentation for the awesome_nested_set plugin.'
-Rake::RDocTask.new(:rdoc) do |rdoc|
- rdoc.rdoc_dir = 'rdoc'
- rdoc.title = 'AwesomeNestedSet'
- rdoc.options << '--line-numbers' << '--inline-source'
- rdoc.rdoc_files.include('README.rdoc')
- rdoc.rdoc_files.include('lib/**/*.rb')
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/awesome_nested_set.gemspec b/trustie2/lib/plugins/awesome_nested_set/awesome_nested_set.gemspec
deleted file mode 100644
index 8e85d6733..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/awesome_nested_set.gemspec
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- encoding: utf-8 -*-
-lib = File.expand_path('../lib/', __FILE__)
-$:.unshift lib unless $:.include?(lib)
-require 'awesome_nested_set/version'
-
-Gem::Specification.new do |s|
- s.name = %q{awesome_nested_set}
- s.version = ::AwesomeNestedSet::VERSION
- s.authors = ["Brandon Keepers", "Daniel Morrison", "Philip Arndt"]
- s.description = %q{An awesome nested set implementation for Active Record}
- s.email = %q{info@collectiveidea.com}
- s.extra_rdoc_files = [
- "README.rdoc"
- ]
- s.files = Dir.glob("lib/**/*") + %w(MIT-LICENSE README.rdoc CHANGELOG)
- s.homepage = %q{http://github.com/collectiveidea/awesome_nested_set}
- s.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"]
- s.require_paths = ["lib"]
- s.rubygems_version = %q{1.3.6}
- s.summary = %q{An awesome nested set implementation for Active Record}
- s.add_runtime_dependency 'activerecord', '>= 3.0.0'
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/init.rb b/trustie2/lib/plugins/awesome_nested_set/init.rb
deleted file mode 100644
index a505b6acf..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/init.rb
+++ /dev/null
@@ -1 +0,0 @@
-require File.dirname(__FILE__) + '/lib/awesome_nested_set'
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set.rb b/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set.rb
deleted file mode 100644
index 022044275..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require 'awesome_nested_set/awesome_nested_set'
-ActiveRecord::Base.send :extend, CollectiveIdea::Acts::NestedSet
-
-if defined?(ActionView)
- require 'awesome_nested_set/helper'
- ActionView::Base.send :include, CollectiveIdea::Acts::NestedSet::Helper
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb b/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb
deleted file mode 100644
index 7f0b23197..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set/awesome_nested_set.rb
+++ /dev/null
@@ -1,601 +0,0 @@
-module CollectiveIdea #:nodoc:
- module Acts #:nodoc:
- module NestedSet #:nodoc:
-
- # This acts provides Nested Set functionality. Nested Set is a smart way to implement
- # an _ordered_ tree, with the added feature that you can select the children and all of their
- # descendants with a single query. The drawback is that insertion or move need some complex
- # sql queries. But everything is done here by this module!
- #
- # Nested sets are appropriate each time you want either an orderd tree (menus,
- # commercial categories) or an efficient way of querying big trees (threaded posts).
- #
- # == API
- #
- # Methods names are aligned with acts_as_tree as much as possible to make replacment from one
- # by another easier.
- #
- # item.children.create(:name => "child1")
- #
-
- # Configuration options are:
- #
- # * +:parent_column+ - specifies the column name to use for keeping the position integer (default: parent_id)
- # * +:left_column+ - column name for left boundry data, default "lft"
- # * +:right_column+ - column name for right boundry data, default "rgt"
- # * +:scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id"
- # (if it hasn't been already) and use that as the foreign key restriction. You
- # can also pass an array to scope by multiple attributes.
- # Example: acts_as_nested_set :scope => [:notable_id, :notable_type]
- # * +:dependent+ - behavior for cascading destroy. If set to :destroy, all the
- # child objects are destroyed alongside this object by calling their destroy
- # method. If set to :delete_all (default), all the child objects are deleted
- # without calling their destroy method.
- # * +:counter_cache+ adds a counter cache for the number of children.
- # defaults to false.
- # Example: acts_as_nested_set :counter_cache => :children_count
- #
- # See CollectiveIdea::Acts::NestedSet::Model::ClassMethods for a list of class methods and
- # CollectiveIdea::Acts::NestedSet::Model for a list of instance methods added
- # to acts_as_nested_set models
- def acts_as_nested_set(options = {})
- options = {
- :parent_column => 'parent_id',
- :left_column => 'lft',
- :right_column => 'rgt',
- :dependent => :delete_all, # or :destroy
- :counter_cache => false,
- :order => 'id'
- }.merge(options)
-
- if options[:scope].is_a?(Symbol) && options[:scope].to_s !~ /_id$/
- options[:scope] = "#{options[:scope]}_id".intern
- end
-
- class_attribute :acts_as_nested_set_options
- self.acts_as_nested_set_options = options
-
- include CollectiveIdea::Acts::NestedSet::Model
- include Columns
- extend Columns
-
- belongs_to :parent, :class_name => self.base_class.to_s,
- :foreign_key => parent_column_name,
- :counter_cache => options[:counter_cache],
- :inverse_of => :children
- has_many :children, :class_name => self.base_class.to_s,
- :foreign_key => parent_column_name, :order => left_column_name,
- :inverse_of => :parent,
- :before_add => options[:before_add],
- :after_add => options[:after_add],
- :before_remove => options[:before_remove],
- :after_remove => options[:after_remove]
-
- attr_accessor :skip_before_destroy
-
- before_create :set_default_left_and_right
- before_save :store_new_parent
- after_save :move_to_new_parent
- before_destroy :destroy_descendants
-
- # no assignment to structure fields
- [left_column_name, right_column_name].each do |column|
- module_eval <<-"end_eval", __FILE__, __LINE__
- def #{column}=(x)
- raise ActiveRecord::ActiveRecordError, "Unauthorized assignment to #{column}: it's an internal field handled by acts_as_nested_set code, use move_to_* methods instead."
- end
- end_eval
- end
-
- define_model_callbacks :move
- end
-
- module Model
- extend ActiveSupport::Concern
-
- module ClassMethods
- # Returns the first root
- def root
- roots.first
- end
-
- def roots
- where(parent_column_name => nil).order(quoted_left_column_name)
- end
-
- def leaves
- where("#{quoted_right_column_name} - #{quoted_left_column_name} = 1").order(quoted_left_column_name)
- end
-
- def valid?
- left_and_rights_valid? && no_duplicates_for_columns? && all_roots_valid?
- end
-
- def left_and_rights_valid?
- joins("LEFT OUTER JOIN #{quoted_table_name} AS parent ON " +
- "#{quoted_table_name}.#{quoted_parent_column_name} = parent.#{primary_key}").
- where(
- "#{quoted_table_name}.#{quoted_left_column_name} IS NULL OR " +
- "#{quoted_table_name}.#{quoted_right_column_name} IS NULL OR " +
- "#{quoted_table_name}.#{quoted_left_column_name} >= " +
- "#{quoted_table_name}.#{quoted_right_column_name} OR " +
- "(#{quoted_table_name}.#{quoted_parent_column_name} IS NOT NULL AND " +
- "(#{quoted_table_name}.#{quoted_left_column_name} <= parent.#{quoted_left_column_name} OR " +
- "#{quoted_table_name}.#{quoted_right_column_name} >= parent.#{quoted_right_column_name}))"
- ).count == 0
- end
-
- def no_duplicates_for_columns?
- scope_string = Array(acts_as_nested_set_options[:scope]).map do |c|
- connection.quote_column_name(c)
- end.push(nil).join(", ")
- [quoted_left_column_name, quoted_right_column_name].all? do |column|
- # No duplicates
- select("#{scope_string}#{column}, COUNT(#{column})").
- group("#{scope_string}#{column}").
- having("COUNT(#{column}) > 1").
- first.nil?
- end
- end
-
- # Wrapper for each_root_valid? that can deal with scope.
- def all_roots_valid?
- if acts_as_nested_set_options[:scope]
- roots.group(scope_column_names).group_by{|record| scope_column_names.collect{|col| record.send(col.to_sym)}}.all? do |scope, grouped_roots|
- each_root_valid?(grouped_roots)
- end
- else
- each_root_valid?(roots)
- end
- end
-
- def each_root_valid?(roots_to_validate)
- left = right = 0
- roots_to_validate.all? do |root|
- (root.left > left && root.right > right).tap do
- left = root.left
- right = root.right
- end
- end
- end
-
- # Rebuilds the left & rights if unset or invalid.
- # Also very useful for converting from acts_as_tree.
- def rebuild!(validate_nodes = true)
- # Don't rebuild a valid tree.
- return true if valid?
-
- scope = lambda{|node|}
- if acts_as_nested_set_options[:scope]
- scope = lambda{|node|
- scope_column_names.inject(""){|str, column_name|
- str << "AND #{connection.quote_column_name(column_name)} = #{connection.quote(node.send(column_name.to_sym))} "
- }
- }
- end
- indices = {}
-
- set_left_and_rights = lambda do |node|
- # set left
- node[left_column_name] = indices[scope.call(node)] += 1
- # find
- where(["#{quoted_parent_column_name} = ? #{scope.call(node)}", node]).order(acts_as_nested_set_options[:order]).each{|n| set_left_and_rights.call(n) }
- # set right
- node[right_column_name] = indices[scope.call(node)] += 1
- node.save!(:validate => validate_nodes)
- end
-
- # Find root node(s)
- root_nodes = where("#{quoted_parent_column_name} IS NULL").order(acts_as_nested_set_options[:order]).each do |root_node|
- # setup index for this scope
- indices[scope.call(root_node)] ||= 0
- set_left_and_rights.call(root_node)
- end
- end
-
- # Iterates over tree elements and determines the current level in the tree.
- # Only accepts default ordering, odering by an other column than lft
- # does not work. This method is much more efficent than calling level
- # because it doesn't require any additional database queries.
- #
- # Example:
- # Category.each_with_level(Category.root.self_and_descendants) do |o, level|
- #
- def each_with_level(objects)
- path = [nil]
- objects.each do |o|
- if o.parent_id != path.last
- # we are on a new level, did we decent or ascent?
- if path.include?(o.parent_id)
- # remove wrong wrong tailing paths elements
- path.pop while path.last != o.parent_id
- else
- path << o.parent_id
- end
- end
- yield(o, path.length - 1)
- end
- end
- end
-
- # Any instance method that returns a collection makes use of Rails 2.1's named_scope (which is bundled for Rails 2.0), so it can be treated as a finder.
- #
- # category.self_and_descendants.count
- # category.ancestors.find(:all, :conditions => "name like '%foo%'")
-
- # Value of the parent column
- def parent_id
- self[parent_column_name]
- end
-
- # Value of the left column
- def left
- self[left_column_name]
- end
-
- # Value of the right column
- def right
- self[right_column_name]
- end
-
- # Returns true if this is a root node.
- def root?
- parent_id.nil?
- end
-
- def leaf?
- new_record? || (right - left == 1)
- end
-
- # Returns true is this is a child node
- def child?
- !parent_id.nil?
- end
-
- # Returns root
- def root
- self_and_ancestors.where(parent_column_name => nil).first
- end
-
- # Returns the array of all parents and self
- def self_and_ancestors
- nested_set_scope.where([
- "#{self.class.quoted_table_name}.#{quoted_left_column_name} <= ? AND #{self.class.quoted_table_name}.#{quoted_right_column_name} >= ?", left, right
- ])
- end
-
- # Returns an array of all parents
- def ancestors
- without_self self_and_ancestors
- end
-
- # Returns the array of all children of the parent, including self
- def self_and_siblings
- nested_set_scope.where(parent_column_name => parent_id)
- end
-
- # Returns the array of all children of the parent, except self
- def siblings
- without_self self_and_siblings
- end
-
- # Returns a set of all of its nested children which do not have children
- def leaves
- descendants.where("#{self.class.quoted_table_name}.#{quoted_right_column_name} - #{self.class.quoted_table_name}.#{quoted_left_column_name} = 1")
- end
-
- # Returns the level of this object in the tree
- # root level is 0
- def level
- parent_id.nil? ? 0 : ancestors.count
- end
-
- # Returns a set of itself and all of its nested children
- def self_and_descendants
- nested_set_scope.where([
- "#{self.class.quoted_table_name}.#{quoted_left_column_name} >= ? AND #{self.class.quoted_table_name}.#{quoted_right_column_name} <= ?", left, right
- ])
- end
-
- # Returns a set of all of its children and nested children
- def descendants
- without_self self_and_descendants
- end
-
- def is_descendant_of?(other)
- other.left < self.left && self.left < other.right && same_scope?(other)
- end
-
- def is_or_is_descendant_of?(other)
- other.left <= self.left && self.left < other.right && same_scope?(other)
- end
-
- def is_ancestor_of?(other)
- self.left < other.left && other.left < self.right && same_scope?(other)
- end
-
- def is_or_is_ancestor_of?(other)
- self.left <= other.left && other.left < self.right && same_scope?(other)
- end
-
- # Check if other model is in the same scope
- def same_scope?(other)
- Array(acts_as_nested_set_options[:scope]).all? do |attr|
- self.send(attr) == other.send(attr)
- end
- end
-
- # Find the first sibling to the left
- def left_sibling
- siblings.where(["#{self.class.quoted_table_name}.#{quoted_left_column_name} < ?", left]).
- order("#{self.class.quoted_table_name}.#{quoted_left_column_name} DESC").last
- end
-
- # Find the first sibling to the right
- def right_sibling
- siblings.where(["#{self.class.quoted_table_name}.#{quoted_left_column_name} > ?", left]).first
- end
-
- # Shorthand method for finding the left sibling and moving to the left of it.
- def move_left
- move_to_left_of left_sibling
- end
-
- # Shorthand method for finding the right sibling and moving to the right of it.
- def move_right
- move_to_right_of right_sibling
- end
-
- # Move the node to the left of another node (you can pass id only)
- def move_to_left_of(node)
- move_to node, :left
- end
-
- # Move the node to the left of another node (you can pass id only)
- def move_to_right_of(node)
- move_to node, :right
- end
-
- # Move the node to the child of another node (you can pass id only)
- def move_to_child_of(node)
- move_to node, :child
- end
-
- # Move the node to root nodes
- def move_to_root
- move_to nil, :root
- end
-
- def move_possible?(target)
- self != target && # Can't target self
- same_scope?(target) && # can't be in different scopes
- # !(left..right).include?(target.left..target.right) # this needs tested more
- # detect impossible move
- !((left <= target.left && right >= target.left) or (left <= target.right && right >= target.right))
- end
-
- def to_text
- self_and_descendants.map do |node|
- "#{'*'*(node.level+1)} #{node.id} #{node.to_s} (#{node.parent_id}, #{node.left}, #{node.right})"
- end.join("\n")
- end
-
- protected
-
- def without_self(scope)
- scope.where(["#{self.class.quoted_table_name}.#{self.class.primary_key} != ?", self])
- end
-
- # All nested set queries should use this nested_set_scope, which performs finds on
- # the base ActiveRecord class, using the :scope declared in the acts_as_nested_set
- # declaration.
- def nested_set_scope(options = {})
- options = {:order => "#{self.class.quoted_table_name}.#{quoted_left_column_name}"}.merge(options)
- scopes = Array(acts_as_nested_set_options[:scope])
- options[:conditions] = scopes.inject({}) do |conditions,attr|
- conditions.merge attr => self[attr]
- end unless scopes.empty?
- self.class.base_class.scoped options
- end
-
- def store_new_parent
- @move_to_new_parent_id = send("#{parent_column_name}_changed?") ? parent_id : false
- true # force callback to return true
- end
-
- def move_to_new_parent
- if @move_to_new_parent_id.nil?
- move_to_root
- elsif @move_to_new_parent_id
- move_to_child_of(@move_to_new_parent_id)
- end
- end
-
- # on creation, set automatically lft and rgt to the end of the tree
- def set_default_left_and_right
- highest_right_row = nested_set_scope(:order => "#{quoted_right_column_name} desc").limit(1).lock(true).first
- maxright = highest_right_row ? (highest_right_row[right_column_name] || 0) : 0
- # adds the new node to the right of all existing nodes
- self[left_column_name] = maxright + 1
- self[right_column_name] = maxright + 2
- end
-
- def in_tenacious_transaction(&block)
- retry_count = 0
- begin
- transaction(&block)
- rescue ActiveRecord::StatementInvalid => error
- raise unless connection.open_transactions.zero?
- raise unless error.message =~ /Deadlock found when trying to get lock|Lock wait timeout exceeded/
- raise unless retry_count < 10
- retry_count += 1
- logger.info "Deadlock detected on retry #{retry_count}, restarting transaction"
- sleep(rand(retry_count)*0.1) # Aloha protocol
- retry
- end
- end
-
- # Prunes a branch off of the tree, shifting all of the elements on the right
- # back to the left so the counts still work.
- def destroy_descendants
- return if right.nil? || left.nil? || skip_before_destroy
-
- in_tenacious_transaction do
- reload_nested_set
- # select the rows in the model that extend past the deletion point and apply a lock
- self.class.base_class.
- select("id").
- where("#{quoted_left_column_name} >= ?", left).
- lock(true).
- all
-
- if acts_as_nested_set_options[:dependent] == :destroy
- descendants.each do |model|
- model.skip_before_destroy = true
- model.destroy
- end
- else
- nested_set_scope.delete_all(
- ["#{quoted_left_column_name} > ? AND #{quoted_right_column_name} < ?",
- left, right]
- )
- end
-
- # update lefts and rights for remaining nodes
- diff = right - left + 1
- nested_set_scope.update_all(
- ["#{quoted_left_column_name} = (#{quoted_left_column_name} - ?)", diff],
- ["#{quoted_left_column_name} > ?", right]
- )
- nested_set_scope.update_all(
- ["#{quoted_right_column_name} = (#{quoted_right_column_name} - ?)", diff],
- ["#{quoted_right_column_name} > ?", right]
- )
-
-reload
- # Don't allow multiple calls to destroy to corrupt the set
- self.skip_before_destroy = true
- end
- end
-
- # reload left, right, and parent
- def reload_nested_set
- reload(
- :select => "#{quoted_left_column_name}, #{quoted_right_column_name}, #{quoted_parent_column_name}",
- :lock => true
- )
- end
-
- def move_to(target, position)
- raise ActiveRecord::ActiveRecordError, "You cannot move a new node" if self.new_record?
- run_callbacks :move do
- in_tenacious_transaction do
- if target.is_a? self.class.base_class
- target.reload_nested_set
- elsif position != :root
- # load object if node is not an object
- target = nested_set_scope.find(target)
- end
- self.reload_nested_set
-
- unless position == :root || move_possible?(target)
- raise ActiveRecord::ActiveRecordError, "Impossible move, target node cannot be inside moved tree."
- end
-
- bound = case position
- when :child; target[right_column_name]
- when :left; target[left_column_name]
- when :right; target[right_column_name] + 1
- when :root; 1
- else raise ActiveRecord::ActiveRecordError, "Position should be :child, :left, :right or :root ('#{position}' received)."
- end
-
- if bound > self[right_column_name]
- bound = bound - 1
- other_bound = self[right_column_name] + 1
- else
- other_bound = self[left_column_name] - 1
- end
-
- # there would be no change
- return if bound == self[right_column_name] || bound == self[left_column_name]
-
- # we have defined the boundaries of two non-overlapping intervals,
- # so sorting puts both the intervals and their boundaries in order
- a, b, c, d = [self[left_column_name], self[right_column_name], bound, other_bound].sort
-
- # select the rows in the model between a and d, and apply a lock
- self.class.base_class.select('id').lock(true).where(
- ["#{quoted_left_column_name} >= :a and #{quoted_right_column_name} <= :d", {:a => a, :d => d}]
- )
-
- new_parent = case position
- when :child; target.id
- when :root; nil
- else target[parent_column_name]
- end
-
- self.nested_set_scope.update_all([
- "#{quoted_left_column_name} = CASE " +
- "WHEN #{quoted_left_column_name} BETWEEN :a AND :b " +
- "THEN #{quoted_left_column_name} + :d - :b " +
- "WHEN #{quoted_left_column_name} BETWEEN :c AND :d " +
- "THEN #{quoted_left_column_name} + :a - :c " +
- "ELSE #{quoted_left_column_name} END, " +
- "#{quoted_right_column_name} = CASE " +
- "WHEN #{quoted_right_column_name} BETWEEN :a AND :b " +
- "THEN #{quoted_right_column_name} + :d - :b " +
- "WHEN #{quoted_right_column_name} BETWEEN :c AND :d " +
- "THEN #{quoted_right_column_name} + :a - :c " +
- "ELSE #{quoted_right_column_name} END, " +
- "#{quoted_parent_column_name} = CASE " +
- "WHEN #{self.class.base_class.primary_key} = :id THEN :new_parent " +
- "ELSE #{quoted_parent_column_name} END",
- {:a => a, :b => b, :c => c, :d => d, :id => self.id, :new_parent => new_parent}
- ])
- end
- target.reload_nested_set if target
- self.reload_nested_set
- end
- end
-
- end
-
- # Mixed into both classes and instances to provide easy access to the column names
- module Columns
- def left_column_name
- acts_as_nested_set_options[:left_column]
- end
-
- def right_column_name
- acts_as_nested_set_options[:right_column]
- end
-
- def parent_column_name
- acts_as_nested_set_options[:parent_column]
- end
-
- def scope_column_names
- Array(acts_as_nested_set_options[:scope])
- end
-
- def quoted_left_column_name
- connection.quote_column_name(left_column_name)
- end
-
- def quoted_right_column_name
- connection.quote_column_name(right_column_name)
- end
-
- def quoted_parent_column_name
- connection.quote_column_name(parent_column_name)
- end
-
- def quoted_scope_column_names
- scope_column_names.collect {|column_name| connection.quote_column_name(column_name) }
- end
- end
-
- end
- end
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set/helper.rb b/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set/helper.rb
deleted file mode 100644
index bfeb18ce4..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set/helper.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-module CollectiveIdea #:nodoc:
- module Acts #:nodoc:
- module NestedSet #:nodoc:
- # This module provides some helpers for the model classes using acts_as_nested_set.
- # It is included by default in all views.
- #
- module Helper
- # Returns options for select.
- # You can exclude some items from the tree.
- # You can pass a block receiving an item and returning the string displayed in the select.
- #
- # == Params
- # * +class_or_item+ - Class name or top level times
- # * +mover+ - The item that is being move, used to exlude impossible moves
- # * +&block+ - a block that will be used to display: { |item| ... item.name }
- #
- # == Usage
- #
- # <%= f.select :parent_id, nested_set_options(Category, @category) {|i|
- # "#{'–' * i.level} #{i.name}"
- # }) %>
- #
- def nested_set_options(class_or_item, mover = nil)
- if class_or_item.is_a? Array
- items = class_or_item.reject { |e| !e.root? }
- else
- class_or_item = class_or_item.roots if class_or_item.is_a?(Class)
- items = Array(class_or_item)
- end
- result = []
- items.each do |root|
- result += root.self_and_descendants.map do |i|
- if mover.nil? || mover.new_record? || mover.move_possible?(i)
- [yield(i), i.id]
- end
- end.compact
- end
- result
- end
-
- end
- end
- end
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb b/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb
deleted file mode 100644
index 755256ab4..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/lib/awesome_nested_set/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module AwesomeNestedSet
- VERSION = '2.1.0' unless defined?(::AwesomeNestedSet::VERSION)
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/rails/init.rb b/trustie2/lib/plugins/awesome_nested_set/rails/init.rb
deleted file mode 100644
index e0a4e8b06..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/rails/init.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'awesome_nested_set/compatability'
-require 'awesome_nested_set'
-
-ActiveRecord::Base.class_eval do
- include CollectiveIdea::Acts::NestedSet
-end
-
-if defined?(ActionView)
- require 'awesome_nested_set/helper'
- ActionView::Base.class_eval do
- include CollectiveIdea::Acts::NestedSet::Helper
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb b/trustie2/lib/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb
deleted file mode 100644
index 1cca71ba8..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/awesome_nested_set/helper_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-require 'spec_helper'
-
-describe "Helper" do
- include CollectiveIdea::Acts::NestedSet::Helper
-
- before(:all) do
- self.class.fixtures :categories
- end
-
- describe "nested_set_options" do
- it "test_nested_set_options" do
- expected = [
- [" Top Level", 1],
- ["- Child 1", 2],
- ['- Child 2', 3],
- ['-- Child 2.1', 4],
- ['- Child 3', 5],
- [" Top Level 2", 6]
- ]
- actual = nested_set_options(Category) do |c|
- "#{'-' * c.level} #{c.name}"
- end
- actual.should == expected
- end
-
- it "test_nested_set_options_with_mover" do
- expected = [
- [" Top Level", 1],
- ["- Child 1", 2],
- ['- Child 3', 5],
- [" Top Level 2", 6]
- ]
- actual = nested_set_options(Category, categories(:child_2)) do |c|
- "#{'-' * c.level} #{c.name}"
- end
- actual.should == expected
- end
-
- it "test_nested_set_options_with_array_as_argument_without_mover" do
- expected = [
- [" Top Level", 1],
- ["- Child 1", 2],
- ['- Child 2', 3],
- ['-- Child 2.1', 4],
- ['- Child 3', 5],
- [" Top Level 2", 6]
- ]
- actual = nested_set_options(Category.all) do |c|
- "#{'-' * c.level} #{c.name}"
- end
- actual.should == expected
- end
-
- it "test_nested_set_options_with_array_as_argument_with_mover" do
- expected = [
- [" Top Level", 1],
- ["- Child 1", 2],
- ['- Child 3', 5],
- [" Top Level 2", 6]
- ]
- actual = nested_set_options(Category.all, categories(:child_2)) do |c|
- "#{'-' * c.level} #{c.name}"
- end
- actual.should == expected
- end
- end
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb b/trustie2/lib/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb
deleted file mode 100644
index 692b123a5..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/awesome_nested_set_spec.rb
+++ /dev/null
@@ -1,841 +0,0 @@
-require 'spec_helper'
-
-describe "AwesomeNestedSet" do
- before(:all) do
- self.class.fixtures :categories, :departments, :notes, :things, :brokens
- end
-
- describe "defaults" do
- it "should have left_column_default" do
- Default.acts_as_nested_set_options[:left_column].should == 'lft'
- end
-
- it "should have right_column_default" do
- Default.acts_as_nested_set_options[:right_column].should == 'rgt'
- end
-
- it "should have parent_column_default" do
- Default.acts_as_nested_set_options[:parent_column].should == 'parent_id'
- end
-
- it "should have scope_default" do
- Default.acts_as_nested_set_options[:scope].should be_nil
- end
-
- it "should have left_column_name" do
- Default.left_column_name.should == 'lft'
- Default.new.left_column_name.should == 'lft'
- RenamedColumns.left_column_name.should == 'red'
- RenamedColumns.new.left_column_name.should == 'red'
- end
-
- it "should have right_column_name" do
- Default.right_column_name.should == 'rgt'
- Default.new.right_column_name.should == 'rgt'
- RenamedColumns.right_column_name.should == 'black'
- RenamedColumns.new.right_column_name.should == 'black'
- end
-
- it "should have parent_column_name" do
- Default.parent_column_name.should == 'parent_id'
- Default.new.parent_column_name.should == 'parent_id'
- RenamedColumns.parent_column_name.should == 'mother_id'
- RenamedColumns.new.parent_column_name.should == 'mother_id'
- end
- end
-
- it "creation_with_altered_column_names" do
- lambda {
- RenamedColumns.create!()
- }.should_not raise_exception
- end
-
- it "creation when existing record has nil left column" do
- assert_nothing_raised do
- Broken.create!
- end
- end
-
- it "quoted_left_column_name" do
- quoted = Default.connection.quote_column_name('lft')
- Default.quoted_left_column_name.should == quoted
- Default.new.quoted_left_column_name.should == quoted
- end
-
- it "quoted_right_column_name" do
- quoted = Default.connection.quote_column_name('rgt')
- Default.quoted_right_column_name.should == quoted
- Default.new.quoted_right_column_name.should == quoted
- end
-
- it "left_column_protected_from_assignment" do
- lambda {
- Category.new.lft = 1
- }.should raise_exception(ActiveRecord::ActiveRecordError)
- end
-
- it "right_column_protected_from_assignment" do
- lambda {
- Category.new.rgt = 1
- }.should raise_exception(ActiveRecord::ActiveRecordError)
- end
-
- it "scoped_appends_id" do
- ScopedCategory.acts_as_nested_set_options[:scope].should == :organization_id
- end
-
- it "roots_class_method" do
- Category.roots.should == Category.find_all_by_parent_id(nil)
- end
-
- it "root_class_method" do
- Category.root.should == categories(:top_level)
- end
-
- it "root" do
- categories(:child_3).root.should == categories(:top_level)
- end
-
- it "root?" do
- categories(:top_level).root?.should be_true
- categories(:top_level_2).root?.should be_true
- end
-
- it "leaves_class_method" do
- Category.find(:all, :conditions => "#{Category.right_column_name} - #{Category.left_column_name} = 1").should == Category.leaves
- Category.leaves.count.should == 4
- Category.leaves.should include(categories(:child_1))
- Category.leaves.should include(categories(:child_2_1))
- Category.leaves.should include(categories(:child_3))
- Category.leaves.should include(categories(:top_level_2))
- end
-
- it "leaf" do
- categories(:child_1).leaf?.should be_true
- categories(:child_2_1).leaf?.should be_true
- categories(:child_3).leaf?.should be_true
- categories(:top_level_2).leaf?.should be_true
-
- categories(:top_level).leaf?.should be_false
- categories(:child_2).leaf?.should be_false
- Category.new.leaf?.should be_false
- end
-
-
- it "parent" do
- categories(:child_2_1).parent.should == categories(:child_2)
- end
-
- it "self_and_ancestors" do
- child = categories(:child_2_1)
- self_and_ancestors = [categories(:top_level), categories(:child_2), child]
- self_and_ancestors.should == child.self_and_ancestors
- end
-
- it "ancestors" do
- child = categories(:child_2_1)
- ancestors = [categories(:top_level), categories(:child_2)]
- ancestors.should == child.ancestors
- end
-
- it "self_and_siblings" do
- child = categories(:child_2)
- self_and_siblings = [categories(:child_1), child, categories(:child_3)]
- self_and_siblings.should == child.self_and_siblings
- lambda do
- tops = [categories(:top_level), categories(:top_level_2)]
- assert_equal tops, categories(:top_level).self_and_siblings
- end.should_not raise_exception
- end
-
- it "siblings" do
- child = categories(:child_2)
- siblings = [categories(:child_1), categories(:child_3)]
- siblings.should == child.siblings
- end
-
- it "leaves" do
- leaves = [categories(:child_1), categories(:child_2_1), categories(:child_3)]
- categories(:top_level).leaves.should == leaves
- end
-
- it "level" do
- categories(:top_level).level.should == 0
- categories(:child_1).level.should == 1
- categories(:child_2_1).level.should == 2
- end
-
- it "has_children?" do
- categories(:child_2_1).children.empty?.should be_true
- categories(:child_2).children.empty?.should be_false
- categories(:top_level).children.empty?.should be_false
- end
-
- it "self_and_descendents" do
- parent = categories(:top_level)
- self_and_descendants = [parent, categories(:child_1), categories(:child_2),
- categories(:child_2_1), categories(:child_3)]
- self_and_descendants.should == parent.self_and_descendants
- self_and_descendants.count.should == parent.self_and_descendants.count
- end
-
- it "descendents" do
- lawyers = Category.create!(:name => "lawyers")
- us = Category.create!(:name => "United States")
- us.move_to_child_of(lawyers)
- patent = Category.create!(:name => "Patent Law")
- patent.move_to_child_of(us)
- lawyers.reload
-
- lawyers.children.size.should == 1
- us.children.size.should == 1
- lawyers.descendants.size.should == 2
- end
-
- it "self_and_descendents" do
- parent = categories(:top_level)
- descendants = [categories(:child_1), categories(:child_2),
- categories(:child_2_1), categories(:child_3)]
- descendants.should == parent.descendants
- end
-
- it "children" do
- category = categories(:top_level)
- category.children.each {|c| category.id.should == c.parent_id }
- end
-
- it "order_of_children" do
- categories(:child_2).move_left
- categories(:child_2).should == categories(:top_level).children[0]
- categories(:child_1).should == categories(:top_level).children[1]
- categories(:child_3).should == categories(:top_level).children[2]
- end
-
- it "is_or_is_ancestor_of?" do
- categories(:top_level).is_or_is_ancestor_of?(categories(:child_1)).should be_true
- categories(:top_level).is_or_is_ancestor_of?(categories(:child_2_1)).should be_true
- categories(:child_2).is_or_is_ancestor_of?(categories(:child_2_1)).should be_true
- categories(:child_2_1).is_or_is_ancestor_of?(categories(:child_2)).should be_false
- categories(:child_1).is_or_is_ancestor_of?(categories(:child_2)).should be_false
- categories(:child_1).is_or_is_ancestor_of?(categories(:child_1)).should be_true
- end
-
- it "is_ancestor_of?" do
- categories(:top_level).is_ancestor_of?(categories(:child_1)).should be_true
- categories(:top_level).is_ancestor_of?(categories(:child_2_1)).should be_true
- categories(:child_2).is_ancestor_of?(categories(:child_2_1)).should be_true
- categories(:child_2_1).is_ancestor_of?(categories(:child_2)).should be_false
- categories(:child_1).is_ancestor_of?(categories(:child_2)).should be_false
- categories(:child_1).is_ancestor_of?(categories(:child_1)).should be_false
- end
-
- it "is_or_is_ancestor_of_with_scope" do
- root = ScopedCategory.root
- child = root.children.first
- root.is_or_is_ancestor_of?(child).should be_true
- child.update_attribute :organization_id, 'different'
- root.is_or_is_ancestor_of?(child).should be_false
- end
-
- it "is_or_is_descendant_of?" do
- categories(:child_1).is_or_is_descendant_of?(categories(:top_level)).should be_true
- categories(:child_2_1).is_or_is_descendant_of?(categories(:top_level)).should be_true
- categories(:child_2_1).is_or_is_descendant_of?(categories(:child_2)).should be_true
- categories(:child_2).is_or_is_descendant_of?(categories(:child_2_1)).should be_false
- categories(:child_2).is_or_is_descendant_of?(categories(:child_1)).should be_false
- categories(:child_1).is_or_is_descendant_of?(categories(:child_1)).should be_true
- end
-
- it "is_descendant_of?" do
- categories(:child_1).is_descendant_of?(categories(:top_level)).should be_true
- categories(:child_2_1).is_descendant_of?(categories(:top_level)).should be_true
- categories(:child_2_1).is_descendant_of?(categories(:child_2)).should be_true
- categories(:child_2).is_descendant_of?(categories(:child_2_1)).should be_false
- categories(:child_2).is_descendant_of?(categories(:child_1)).should be_false
- categories(:child_1).is_descendant_of?(categories(:child_1)).should be_false
- end
-
- it "is_or_is_descendant_of_with_scope" do
- root = ScopedCategory.root
- child = root.children.first
- child.is_or_is_descendant_of?(root).should be_true
- child.update_attribute :organization_id, 'different'
- child.is_or_is_descendant_of?(root).should be_false
- end
-
- it "same_scope?" do
- root = ScopedCategory.root
- child = root.children.first
- child.same_scope?(root).should be_true
- child.update_attribute :organization_id, 'different'
- child.same_scope?(root).should be_false
- end
-
- it "left_sibling" do
- categories(:child_1).should == categories(:child_2).left_sibling
- categories(:child_2).should == categories(:child_3).left_sibling
- end
-
- it "left_sibling_of_root" do
- categories(:top_level).left_sibling.should be_nil
- end
-
- it "left_sibling_without_siblings" do
- categories(:child_2_1).left_sibling.should be_nil
- end
-
- it "left_sibling_of_leftmost_node" do
- categories(:child_1).left_sibling.should be_nil
- end
-
- it "right_sibling" do
- categories(:child_3).should == categories(:child_2).right_sibling
- categories(:child_2).should == categories(:child_1).right_sibling
- end
-
- it "right_sibling_of_root" do
- categories(:top_level_2).should == categories(:top_level).right_sibling
- categories(:top_level_2).right_sibling.should be_nil
- end
-
- it "right_sibling_without_siblings" do
- categories(:child_2_1).right_sibling.should be_nil
- end
-
- it "right_sibling_of_rightmost_node" do
- categories(:child_3).right_sibling.should be_nil
- end
-
- it "move_left" do
- categories(:child_2).move_left
- categories(:child_2).left_sibling.should be_nil
- categories(:child_1).should == categories(:child_2).right_sibling
- Category.valid?.should be_true
- end
-
- it "move_right" do
- categories(:child_2).move_right
- categories(:child_2).right_sibling.should be_nil
- categories(:child_3).should == categories(:child_2).left_sibling
- Category.valid?.should be_true
- end
-
- it "move_to_left_of" do
- categories(:child_3).move_to_left_of(categories(:child_1))
- categories(:child_3).left_sibling.should be_nil
- categories(:child_1).should == categories(:child_3).right_sibling
- Category.valid?.should be_true
- end
-
- it "move_to_right_of" do
- categories(:child_1).move_to_right_of(categories(:child_3))
- categories(:child_1).right_sibling.should be_nil
- categories(:child_3).should == categories(:child_1).left_sibling
- Category.valid?.should be_true
- end
-
- it "move_to_root" do
- categories(:child_2).move_to_root
- categories(:child_2).parent.should be_nil
- categories(:child_2).level.should == 0
- categories(:child_2_1).level.should == 1
- categories(:child_2).left.should == 1
- categories(:child_2).right.should == 4
- Category.valid?.should be_true
- end
-
- it "move_to_child_of" do
- categories(:child_1).move_to_child_of(categories(:child_3))
- categories(:child_3).id.should == categories(:child_1).parent_id
- Category.valid?.should be_true
- end
-
- it "move_to_child_of_appends_to_end" do
- child = Category.create! :name => 'New Child'
- child.move_to_child_of categories(:top_level)
- child.should == categories(:top_level).children.last
- end
-
- it "subtree_move_to_child_of" do
- categories(:child_2).left.should == 4
- categories(:child_2).right.should == 7
-
- categories(:child_1).left.should == 2
- categories(:child_1).right.should == 3
-
- categories(:child_2).move_to_child_of(categories(:child_1))
- Category.valid?.should be_true
- categories(:child_1).id.should == categories(:child_2).parent_id
-
- categories(:child_2).left.should == 3
- categories(:child_2).right.should == 6
- categories(:child_1).left.should == 2
- categories(:child_1).right.should == 7
- end
-
- it "slightly_difficult_move_to_child_of" do
- categories(:top_level_2).left.should == 11
- categories(:top_level_2).right.should == 12
-
- # create a new top-level node and move single-node top-level tree inside it.
- new_top = Category.create(:name => 'New Top')
- new_top.left.should == 13
- new_top.right.should == 14
-
- categories(:top_level_2).move_to_child_of(new_top)
-
- Category.valid?.should be_true
- new_top.id.should == categories(:top_level_2).parent_id
-
- categories(:top_level_2).left.should == 12
- categories(:top_level_2).right.should == 13
- new_top.left.should == 11
- new_top.right.should == 14
- end
-
- it "difficult_move_to_child_of" do
- categories(:top_level).left.should == 1
- categories(:top_level).right.should == 10
- categories(:child_2_1).left.should == 5
- categories(:child_2_1).right.should == 6
-
- # create a new top-level node and move an entire top-level tree inside it.
- new_top = Category.create(:name => 'New Top')
- categories(:top_level).move_to_child_of(new_top)
- categories(:child_2_1).reload
- Category.valid?.should be_true
- new_top.id.should == categories(:top_level).parent_id
-
- categories(:top_level).left.should == 4
- categories(:top_level).right.should == 13
- categories(:child_2_1).left.should == 8
- categories(:child_2_1).right.should == 9
- end
-
- #rebuild swaps the position of the 2 children when added using move_to_child twice onto same parent
- it "move_to_child_more_than_once_per_parent_rebuild" do
- root1 = Category.create(:name => 'Root1')
- root2 = Category.create(:name => 'Root2')
- root3 = Category.create(:name => 'Root3')
-
- root2.move_to_child_of root1
- root3.move_to_child_of root1
-
- output = Category.roots.last.to_text
- Category.update_all('lft = null, rgt = null')
- Category.rebuild!
-
- Category.roots.last.to_text.should == output
- end
-
- # doing move_to_child twice onto same parent from the furthest right first
- it "move_to_child_more_than_once_per_parent_outside_in" do
- node1 = Category.create(:name => 'Node-1')
- node2 = Category.create(:name => 'Node-2')
- node3 = Category.create(:name => 'Node-3')
-
- node2.move_to_child_of node1
- node3.move_to_child_of node1
-
- output = Category.roots.last.to_text
- Category.update_all('lft = null, rgt = null')
- Category.rebuild!
-
- Category.roots.last.to_text.should == output
- end
-
- it "should be able to rebuild without validating each record" do
- root1 = Category.create(:name => 'Root1')
- root2 = Category.create(:name => 'Root2')
- root3 = Category.create(:name => 'Root3')
-
- root2.move_to_child_of root1
- root3.move_to_child_of root1
-
- root2.name = nil
- root2.save!(:validate => false)
-
- output = Category.roots.last.to_text
- Category.update_all('lft = null, rgt = null')
- Category.rebuild!(false)
-
- Category.roots.last.to_text.should == output
- end
-
- it "valid_with_null_lefts" do
- Category.valid?.should be_true
- Category.update_all('lft = null')
- Category.valid?.should be_false
- end
-
- it "valid_with_null_rights" do
- Category.valid?.should be_true
- Category.update_all('rgt = null')
- Category.valid?.should be_false
- end
-
- it "valid_with_missing_intermediate_node" do
- # Even though child_2_1 will still exist, it is a sign of a sloppy delete, not an invalid tree.
- Category.valid?.should be_true
- Category.delete(categories(:child_2).id)
- Category.valid?.should be_true
- end
-
- it "valid_with_overlapping_and_rights" do
- Category.valid?.should be_true
- categories(:top_level_2)['lft'] = 0
- categories(:top_level_2).save
- Category.valid?.should be_false
- end
-
- it "rebuild" do
- Category.valid?.should be_true
- before_text = Category.root.to_text
- Category.update_all('lft = null, rgt = null')
- Category.rebuild!
- Category.valid?.should be_true
- before_text.should == Category.root.to_text
- end
-
- it "move_possible_for_sibling" do
- categories(:child_2).move_possible?(categories(:child_1)).should be_true
- end
-
- it "move_not_possible_to_self" do
- categories(:top_level).move_possible?(categories(:top_level)).should be_false
- end
-
- it "move_not_possible_to_parent" do
- categories(:top_level).descendants.each do |descendant|
- categories(:top_level).move_possible?(descendant).should be_false
- descendant.move_possible?(categories(:top_level)).should be_true
- end
- end
-
- it "is_or_is_ancestor_of?" do
- [:child_1, :child_2, :child_2_1, :child_3].each do |c|
- categories(:top_level).is_or_is_ancestor_of?(categories(c)).should be_true
- end
- categories(:top_level).is_or_is_ancestor_of?(categories(:top_level_2)).should be_false
- end
-
- it "left_and_rights_valid_with_blank_left" do
- Category.left_and_rights_valid?.should be_true
- categories(:child_2)[:lft] = nil
- categories(:child_2).save(:validate => false)
- Category.left_and_rights_valid?.should be_false
- end
-
- it "left_and_rights_valid_with_blank_right" do
- Category.left_and_rights_valid?.should be_true
- categories(:child_2)[:rgt] = nil
- categories(:child_2).save(:validate => false)
- Category.left_and_rights_valid?.should be_false
- end
-
- it "left_and_rights_valid_with_equal" do
- Category.left_and_rights_valid?.should be_true
- categories(:top_level_2)[:lft] = categories(:top_level_2)[:rgt]
- categories(:top_level_2).save(:validate => false)
- Category.left_and_rights_valid?.should be_false
- end
-
- it "left_and_rights_valid_with_left_equal_to_parent" do
- Category.left_and_rights_valid?.should be_true
- categories(:child_2)[:lft] = categories(:top_level)[:lft]
- categories(:child_2).save(:validate => false)
- Category.left_and_rights_valid?.should be_false
- end
-
- it "left_and_rights_valid_with_right_equal_to_parent" do
- Category.left_and_rights_valid?.should be_true
- categories(:child_2)[:rgt] = categories(:top_level)[:rgt]
- categories(:child_2).save(:validate => false)
- Category.left_and_rights_valid?.should be_false
- end
-
- it "moving_dirty_objects_doesnt_invalidate_tree" do
- r1 = Category.create :name => "Test 1"
- r2 = Category.create :name => "Test 2"
- r3 = Category.create :name => "Test 3"
- r4 = Category.create :name => "Test 4"
- nodes = [r1, r2, r3, r4]
-
- r2.move_to_child_of(r1)
- Category.valid?.should be_true
-
- r3.move_to_child_of(r1)
- Category.valid?.should be_true
-
- r4.move_to_child_of(r2)
- Category.valid?.should be_true
- end
-
- it "multi_scoped_no_duplicates_for_columns?" do
- lambda {
- Note.no_duplicates_for_columns?
- }.should_not raise_exception
- end
-
- it "multi_scoped_all_roots_valid?" do
- lambda {
- Note.all_roots_valid?
- }.should_not raise_exception
- end
-
- it "multi_scoped" do
- note1 = Note.create!(:body => "A", :notable_id => 2, :notable_type => 'Category')
- note2 = Note.create!(:body => "B", :notable_id => 2, :notable_type => 'Category')
- note3 = Note.create!(:body => "C", :notable_id => 2, :notable_type => 'Default')
-
- [note1, note2].should == note1.self_and_siblings
- [note3].should == note3.self_and_siblings
- end
-
- it "multi_scoped_rebuild" do
- root = Note.create!(:body => "A", :notable_id => 3, :notable_type => 'Category')
- child1 = Note.create!(:body => "B", :notable_id => 3, :notable_type => 'Category')
- child2 = Note.create!(:body => "C", :notable_id => 3, :notable_type => 'Category')
-
- child1.move_to_child_of root
- child2.move_to_child_of root
-
- Note.update_all('lft = null, rgt = null')
- Note.rebuild!
-
- Note.roots.find_by_body('A').should == root
- [child1, child2].should == Note.roots.find_by_body('A').children
- end
-
- it "same_scope_with_multi_scopes" do
- lambda {
- notes(:scope1).same_scope?(notes(:child_1))
- }.should_not raise_exception
- notes(:scope1).same_scope?(notes(:child_1)).should be_true
- notes(:child_1).same_scope?(notes(:scope1)).should be_true
- notes(:scope1).same_scope?(notes(:scope2)).should be_false
- end
-
- it "quoting_of_multi_scope_column_names" do
- ["\"notable_id\"", "\"notable_type\""].should == Note.quoted_scope_column_names
- end
-
- it "equal_in_same_scope" do
- notes(:scope1).should == notes(:scope1)
- notes(:scope1).should_not == notes(:child_1)
- end
-
- it "equal_in_different_scopes" do
- notes(:scope1).should_not == notes(:scope2)
- end
-
- it "delete_does_not_invalidate" do
- Category.acts_as_nested_set_options[:dependent] = :delete
- categories(:child_2).destroy
- Category.valid?.should be_true
- end
-
- it "destroy_does_not_invalidate" do
- Category.acts_as_nested_set_options[:dependent] = :destroy
- categories(:child_2).destroy
- Category.valid?.should be_true
- end
-
- it "destroy_multiple_times_does_not_invalidate" do
- Category.acts_as_nested_set_options[:dependent] = :destroy
- categories(:child_2).destroy
- categories(:child_2).destroy
- Category.valid?.should be_true
- end
-
- it "assigning_parent_id_on_create" do
- category = Category.create!(:name => "Child", :parent_id => categories(:child_2).id)
- categories(:child_2).should == category.parent
- categories(:child_2).id.should == category.parent_id
- category.left.should_not be_nil
- category.right.should_not be_nil
- Category.valid?.should be_true
- end
-
- it "assigning_parent_on_create" do
- category = Category.create!(:name => "Child", :parent => categories(:child_2))
- categories(:child_2).should == category.parent
- categories(:child_2).id.should == category.parent_id
- category.left.should_not be_nil
- category.right.should_not be_nil
- Category.valid?.should be_true
- end
-
- it "assigning_parent_id_to_nil_on_create" do
- category = Category.create!(:name => "New Root", :parent_id => nil)
- category.parent.should be_nil
- category.parent_id.should be_nil
- category.left.should_not be_nil
- category.right.should_not be_nil
- Category.valid?.should be_true
- end
-
- it "assigning_parent_id_on_update" do
- category = categories(:child_2_1)
- category.parent_id = categories(:child_3).id
- category.save
- category.reload
- categories(:child_3).reload
- categories(:child_3).should == category.parent
- categories(:child_3).id.should == category.parent_id
- Category.valid?.should be_true
- end
-
- it "assigning_parent_on_update" do
- category = categories(:child_2_1)
- category.parent = categories(:child_3)
- category.save
- category.reload
- categories(:child_3).reload
- categories(:child_3).should == category.parent
- categories(:child_3).id.should == category.parent_id
- Category.valid?.should be_true
- end
-
- it "assigning_parent_id_to_nil_on_update" do
- category = categories(:child_2_1)
- category.parent_id = nil
- category.save
- category.parent.should be_nil
- category.parent_id.should be_nil
- Category.valid?.should be_true
- end
-
- it "creating_child_from_parent" do
- category = categories(:child_2).children.create!(:name => "Child")
- categories(:child_2).should == category.parent
- categories(:child_2).id.should == category.parent_id
- category.left.should_not be_nil
- category.right.should_not be_nil
- Category.valid?.should be_true
- end
-
- def check_structure(entries, structure)
- structure = structure.dup
- Category.each_with_level(entries) do |category, level|
- expected_level, expected_name = structure.shift
- expected_name.should == category.name
- expected_level.should == level
- end
- end
-
- it "each_with_level" do
- levels = [
- [0, "Top Level"],
- [1, "Child 1"],
- [1, "Child 2"],
- [2, "Child 2.1"],
- [1, "Child 3" ]]
-
- check_structure(Category.root.self_and_descendants, levels)
-
- # test some deeper structures
- category = Category.find_by_name("Child 1")
- c1 = Category.new(:name => "Child 1.1")
- c2 = Category.new(:name => "Child 1.1.1")
- c3 = Category.new(:name => "Child 1.1.1.1")
- c4 = Category.new(:name => "Child 1.2")
- [c1, c2, c3, c4].each(&:save!)
-
- c1.move_to_child_of(category)
- c2.move_to_child_of(c1)
- c3.move_to_child_of(c2)
- c4.move_to_child_of(category)
-
- levels = [
- [0, "Top Level"],
- [1, "Child 1"],
- [2, "Child 1.1"],
- [3, "Child 1.1.1"],
- [4, "Child 1.1.1.1"],
- [2, "Child 1.2"],
- [1, "Child 2"],
- [2, "Child 2.1"],
- [1, "Child 3" ]]
-
- check_structure(Category.root.self_and_descendants, levels)
- end
-
- it "should not error on a model with attr_accessible" do
- model = Class.new(ActiveRecord::Base)
- model.table_name = 'categories'
- model.attr_accessible :name
- lambda {
- model.acts_as_nested_set
- model.new(:name => 'foo')
- }.should_not raise_exception
- end
-
- describe "before_move_callback" do
- it "should fire the callback" do
- categories(:child_2).should_receive(:custom_before_move)
- categories(:child_2).move_to_root
- end
-
- it "should stop move when callback returns false" do
- Category.test_allows_move = false
- categories(:child_3).move_to_root.should be_false
- categories(:child_3).root?.should be_false
- end
-
- it "should not halt save actions" do
- Category.test_allows_move = false
- categories(:child_3).parent_id = nil
- categories(:child_3).save.should be_true
- end
- end
-
- describe "counter_cache" do
-
- it "should allow use of a counter cache for children" do
- note1 = things(:parent1)
- note1.children.count.should == 2
- end
-
- it "should increment the counter cache on create" do
- note1 = things(:parent1)
- note1.children.count.should == 2
- note1[:children_count].should == 2
- note1.children.create :body => 'Child 3'
- note1.children.count.should == 3
- note1.reload
- note1[:children_count].should == 3
- end
-
- it "should decrement the counter cache on destroy" do
- note1 = things(:parent1)
- note1.children.count.should == 2
- note1[:children_count].should == 2
- note1.children.last.destroy
- note1.children.count.should == 1
- note1.reload
- note1[:children_count].should == 1
- end
- end
-
- describe "association callbacks on children" do
- it "should call the appropriate callbacks on the children :has_many association " do
- root = DefaultWithCallbacks.create
- root.should_not be_new_record
-
- child = root.children.build
-
- root.before_add.should == child
- root.after_add.should == child
-
- root.before_remove.should_not == child
- root.after_remove.should_not == child
-
- child.save.should be_true
- root.children.delete(child).should be_true
-
- root.before_remove.should == child
- root.after_remove.should == child
- end
- end
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/db/database.yml b/trustie2/lib/plugins/awesome_nested_set/spec/db/database.yml
deleted file mode 100644
index eaa5ed3a0..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/db/database.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-sqlite3:
- adapter: <%= "jdbc" if defined? JRUBY_VERSION %>sqlite3
- database: awesome_nested_set.sqlite3.db
-sqlite3mem:
- adapter: <%= "jdbc" if defined? JRUBY_VERSION %>sqlite3
- database: ":memory:"
-postgresql:
- adapter: postgresql
- username: postgres
- password: postgres
- database: awesome_nested_set_plugin_test
- min_messages: ERROR
-mysql:
- adapter: mysql2
- host: localhost
- username: root
- password:
- database: awesome_nested_set_plugin_test
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/db/schema.rb b/trustie2/lib/plugins/awesome_nested_set/spec/db/schema.rb
deleted file mode 100644
index dcdcde814..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/db/schema.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-ActiveRecord::Schema.define(:version => 0) do
-
- create_table :categories, :force => true do |t|
- t.column :name, :string
- t.column :parent_id, :integer
- t.column :lft, :integer
- t.column :rgt, :integer
- t.column :organization_id, :integer
- end
-
- create_table :departments, :force => true do |t|
- t.column :name, :string
- end
-
- create_table :notes, :force => true do |t|
- t.column :body, :text
- t.column :parent_id, :integer
- t.column :lft, :integer
- t.column :rgt, :integer
- t.column :notable_id, :integer
- t.column :notable_type, :string
- end
-
- create_table :renamed_columns, :force => true do |t|
- t.column :name, :string
- t.column :mother_id, :integer
- t.column :red, :integer
- t.column :black, :integer
- end
-
- create_table :things, :force => true do |t|
- t.column :body, :text
- t.column :parent_id, :integer
- t.column :lft, :integer
- t.column :rgt, :integer
- t.column :children_count, :integer
- end
-
- create_table :brokens, :force => true do |t|
- t.column :name, :string
- t.column :parent_id, :integer
- t.column :lft, :integer
- t.column :rgt, :integer
- end
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/brokens.yml b/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/brokens.yml
deleted file mode 100644
index 3cb6ce915..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/brokens.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-one:
- id: 1
- name: One
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/categories.yml b/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/categories.yml
deleted file mode 100644
index bc8e078e8..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/categories.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-top_level:
- id: 1
- name: Top Level
- lft: 1
- rgt: 10
-child_1:
- id: 2
- name: Child 1
- parent_id: 1
- lft: 2
- rgt: 3
-child_2:
- id: 3
- name: Child 2
- parent_id: 1
- lft: 4
- rgt: 7
-child_2_1:
- id: 4
- name: Child 2.1
- parent_id: 3
- lft: 5
- rgt: 6
-child_3:
- id: 5
- name: Child 3
- parent_id: 1
- lft: 8
- rgt: 9
-top_level_2:
- id: 6
- name: Top Level 2
- lft: 11
- rgt: 12
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/departments.yml b/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/departments.yml
deleted file mode 100644
index e50a944f1..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/departments.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-top:
- id: 1
- name: Top
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/notes.yml b/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/notes.yml
deleted file mode 100644
index 004a5335a..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/notes.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-scope1:
- id: 1
- body: Top Level
- lft: 1
- rgt: 10
- notable_id: 1
- notable_type: Category
-child_1:
- id: 2
- body: Child 1
- parent_id: 1
- lft: 2
- rgt: 3
- notable_id: 1
- notable_type: Category
-child_2:
- id: 3
- body: Child 2
- parent_id: 1
- lft: 4
- rgt: 7
- notable_id: 1
- notable_type: Category
-child_3:
- id: 4
- body: Child 3
- parent_id: 1
- lft: 8
- rgt: 9
- notable_id: 1
- notable_type: Category
-scope2:
- id: 5
- body: Top Level 2
- lft: 1
- rgt: 2
- notable_id: 1
- notable_type: Departments
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/things.yml b/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/things.yml
deleted file mode 100644
index 207a682ed..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/fixtures/things.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-parent1:
- id: 1
- body: Top Level
- lft: 1
- rgt: 10
- children_count: 2
-child_1:
- id: 2
- body: Child 1
- parent_id: 1
- lft: 2
- rgt: 3
- children_count: 0
-child_2:
- id: 3
- body: Child 2
- parent_id: 1
- lft: 4
- rgt: 7
- children_count: 0
-child_2_1:
- id: 4
- body: Child 2.1
- parent_id: 3
- lft: 8
- rgt: 9
- children_count: 0
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/spec_helper.rb b/trustie2/lib/plugins/awesome_nested_set/spec/spec_helper.rb
deleted file mode 100644
index c9cf43d88..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/spec_helper.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-$:.unshift(File.dirname(__FILE__) + '/../lib')
-plugin_test_dir = File.dirname(__FILE__)
-
-require 'rubygems'
-require 'bundler/setup'
-
-require 'rspec'
-require 'logger'
-
-require 'active_support'
-require 'active_model'
-require 'active_record'
-require 'action_controller'
-
-require 'awesome_nested_set'
-
-ActiveRecord::Base.logger = Logger.new(plugin_test_dir + "/debug.log")
-
-require 'yaml'
-require 'erb'
-ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(plugin_test_dir + "/db/database.yml")).result)
-ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite3mem")
-ActiveRecord::Migration.verbose = false
-load(File.join(plugin_test_dir, "db", "schema.rb"))
-
-require 'support/models'
-
-require 'rspec/rails'
-RSpec.configure do |config|
- config.fixture_path = "#{plugin_test_dir}/fixtures"
- config.use_transactional_fixtures = true
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/spec/support/models.rb b/trustie2/lib/plugins/awesome_nested_set/spec/support/models.rb
deleted file mode 100644
index fadb0dc0b..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/spec/support/models.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-class Note < ActiveRecord::Base
- acts_as_nested_set :scope => [:notable_id, :notable_type]
-end
-
-class Default < ActiveRecord::Base
- self.table_name = 'categories'
- acts_as_nested_set
-end
-
-class ScopedCategory < ActiveRecord::Base
- self.table_name = 'categories'
- acts_as_nested_set :scope => :organization
-end
-
-class RenamedColumns < ActiveRecord::Base
- acts_as_nested_set :parent_column => 'mother_id', :left_column => 'red', :right_column => 'black'
-end
-
-class Category < ActiveRecord::Base
- acts_as_nested_set
-
- validates_presence_of :name
-
- # Setup a callback that we can switch to true or false per-test
- set_callback :move, :before, :custom_before_move
- cattr_accessor :test_allows_move
- @@test_allows_move = true
- def custom_before_move
- @@test_allows_move
- end
-
- def to_s
- name
- end
-
- def recurse &block
- block.call self, lambda{
- self.children.each do |child|
- child.recurse &block
- end
- }
- end
-end
-
-class Thing < ActiveRecord::Base
- acts_as_nested_set :counter_cache => 'children_count'
-end
-
-class DefaultWithCallbacks < ActiveRecord::Base
-
- self.table_name = 'categories'
-
- attr_accessor :before_add, :after_add, :before_remove, :after_remove
-
- acts_as_nested_set :before_add => :do_before_add_stuff,
- :after_add => :do_after_add_stuff,
- :before_remove => :do_before_remove_stuff,
- :after_remove => :do_after_remove_stuff
-
- private
-
- [ :before_add, :after_add, :before_remove, :after_remove ].each do |hook_name|
- define_method "do_#{hook_name}_stuff" do |child_node|
- self.send("#{hook_name}=", child_node)
- end
- end
-
-end
-
-class Broken < ActiveRecord::Base
- acts_as_nested_set
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/test/awesome_nested_set/helper_test.rb b/trustie2/lib/plugins/awesome_nested_set/test/awesome_nested_set/helper_test.rb
deleted file mode 100644
index 6122a0e60..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/test/awesome_nested_set/helper_test.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-
-module CollectiveIdea
- module Acts #:nodoc:
- module NestedSet #:nodoc:
- class AwesomeNestedSetTest < Test::Unit::TestCase
- include Helper
- fixtures :categories
-
- def test_nested_set_options
- expected = [
- [" Top Level", 1],
- ["- Child 1", 2],
- ['- Child 2', 3],
- ['-- Child 2.1', 4],
- ['- Child 3', 5],
- [" Top Level 2", 6]
- ]
- actual = nested_set_options(Category) do |c|
- "#{'-' * c.level} #{c.name}"
- end
- assert_equal expected, actual
- end
-
- def test_nested_set_options_with_mover
- expected = [
- [" Top Level", 1],
- ["- Child 1", 2],
- ['- Child 3', 5],
- [" Top Level 2", 6]
- ]
- actual = nested_set_options(Category, categories(:child_2)) do |c|
- "#{'-' * c.level} #{c.name}"
- end
- assert_equal expected, actual
- end
-
- end
- end
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/test/awesome_nested_set_test.rb b/trustie2/lib/plugins/awesome_nested_set/test/awesome_nested_set_test.rb
deleted file mode 100644
index 9f94b43d8..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/test/awesome_nested_set_test.rb
+++ /dev/null
@@ -1,603 +0,0 @@
-require File.dirname(__FILE__) + '/test_helper'
-
-class Note < ActiveRecord::Base
- acts_as_nested_set :scope => [:notable_id, :notable_type]
-end
-
-class AwesomeNestedSetTest < Test::Unit::TestCase
-
- class Default < ActiveRecord::Base
- acts_as_nested_set
- self.table_name = 'categories'
- end
- class Scoped < ActiveRecord::Base
- acts_as_nested_set :scope => :organization
- self.table_name = 'categories'
- end
-
- def test_left_column_default
- assert_equal 'lft', Default.acts_as_nested_set_options[:left_column]
- end
-
- def test_right_column_default
- assert_equal 'rgt', Default.acts_as_nested_set_options[:right_column]
- end
-
- def test_parent_column_default
- assert_equal 'parent_id', Default.acts_as_nested_set_options[:parent_column]
- end
-
- def test_scope_default
- assert_nil Default.acts_as_nested_set_options[:scope]
- end
-
- def test_left_column_name
- assert_equal 'lft', Default.left_column_name
- assert_equal 'lft', Default.new.left_column_name
- end
-
- def test_right_column_name
- assert_equal 'rgt', Default.right_column_name
- assert_equal 'rgt', Default.new.right_column_name
- end
-
- def test_parent_column_name
- assert_equal 'parent_id', Default.parent_column_name
- assert_equal 'parent_id', Default.new.parent_column_name
- end
-
- def test_quoted_left_column_name
- quoted = Default.connection.quote_column_name('lft')
- assert_equal quoted, Default.quoted_left_column_name
- assert_equal quoted, Default.new.quoted_left_column_name
- end
-
- def test_quoted_right_column_name
- quoted = Default.connection.quote_column_name('rgt')
- assert_equal quoted, Default.quoted_right_column_name
- assert_equal quoted, Default.new.quoted_right_column_name
- end
-
- def test_left_column_protected_from_assignment
- assert_raises(ActiveRecord::ActiveRecordError) { Category.new.lft = 1 }
- end
-
- def test_right_column_protected_from_assignment
- assert_raises(ActiveRecord::ActiveRecordError) { Category.new.rgt = 1 }
- end
-
- def test_parent_column_protected_from_assignment
- assert_raises(ActiveRecord::ActiveRecordError) { Category.new.parent_id = 1 }
- end
-
- def test_colums_protected_on_initialize
- c = Category.new(:lft => 1, :rgt => 2, :parent_id => 3)
- assert_nil c.lft
- assert_nil c.rgt
- assert_nil c.parent_id
- end
-
- def test_scoped_appends_id
- assert_equal :organization_id, Scoped.acts_as_nested_set_options[:scope]
- end
-
- def test_roots_class_method
- assert_equal Category.find_all_by_parent_id(nil), Category.roots
- end
-
- def test_root_class_method
- assert_equal categories(:top_level), Category.root
- end
-
- def test_root
- assert_equal categories(:top_level), categories(:child_3).root
- end
-
- def test_root?
- assert categories(:top_level).root?
- assert categories(:top_level_2).root?
- end
-
- def test_leaves_class_method
- assert_equal Category.find(:all, :conditions => "#{Category.right_column_name} - #{Category.left_column_name} = 1"), Category.leaves
- assert_equal Category.leaves.count, 4
- assert (Category.leaves.include? categories(:child_1))
- assert (Category.leaves.include? categories(:child_2_1))
- assert (Category.leaves.include? categories(:child_3))
- assert (Category.leaves.include? categories(:top_level_2))
- end
-
- def test_leaf
- assert categories(:child_1).leaf?
- assert categories(:child_2_1).leaf?
- assert categories(:child_3).leaf?
- assert categories(:top_level_2).leaf?
-
- assert !categories(:top_level).leaf?
- assert !categories(:child_2).leaf?
- end
-
- def test_parent
- assert_equal categories(:child_2), categories(:child_2_1).parent
- end
-
- def test_self_and_ancestors
- child = categories(:child_2_1)
- self_and_ancestors = [categories(:top_level), categories(:child_2), child]
- assert_equal self_and_ancestors, child.self_and_ancestors
- end
-
- def test_ancestors
- child = categories(:child_2_1)
- ancestors = [categories(:top_level), categories(:child_2)]
- assert_equal ancestors, child.ancestors
- end
-
- def test_self_and_siblings
- child = categories(:child_2)
- self_and_siblings = [categories(:child_1), child, categories(:child_3)]
- assert_equal self_and_siblings, child.self_and_siblings
- assert_nothing_raised do
- tops = [categories(:top_level), categories(:top_level_2)]
- assert_equal tops, categories(:top_level).self_and_siblings
- end
- end
-
- def test_siblings
- child = categories(:child_2)
- siblings = [categories(:child_1), categories(:child_3)]
- assert_equal siblings, child.siblings
- end
-
- def test_leaves
- leaves = [categories(:child_1), categories(:child_2_1), categories(:child_3), categories(:top_level_2)]
- assert categories(:top_level).leaves, leaves
- end
-
- def test_level
- assert_equal 0, categories(:top_level).level
- assert_equal 1, categories(:child_1).level
- assert_equal 2, categories(:child_2_1).level
- end
-
- def test_has_children?
- assert categories(:child_2_1).children.empty?
- assert !categories(:child_2).children.empty?
- assert !categories(:top_level).children.empty?
- end
-
- def test_self_and_descendents
- parent = categories(:top_level)
- self_and_descendants = [parent, categories(:child_1), categories(:child_2),
- categories(:child_2_1), categories(:child_3)]
- assert_equal self_and_descendants, parent.self_and_descendants
- assert_equal self_and_descendants, parent.self_and_descendants.count
- end
-
- def test_descendents
- lawyers = Category.create!(:name => "lawyers")
- us = Category.create!(:name => "United States")
- us.move_to_child_of(lawyers)
- patent = Category.create!(:name => "Patent Law")
- patent.move_to_child_of(us)
- lawyers.reload
-
- assert_equal 1, lawyers.children.size
- assert_equal 1, us.children.size
- assert_equal 2, lawyers.descendants.size
- end
-
- def test_self_and_descendents
- parent = categories(:top_level)
- descendants = [categories(:child_1), categories(:child_2),
- categories(:child_2_1), categories(:child_3)]
- assert_equal descendants, parent.descendants
- end
-
- def test_children
- category = categories(:top_level)
- category.children.each {|c| assert_equal category.id, c.parent_id }
- end
-
- def test_is_or_is_ancestor_of?
- assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_1))
- assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_2_1))
- assert categories(:child_2).is_or_is_ancestor_of?(categories(:child_2_1))
- assert !categories(:child_2_1).is_or_is_ancestor_of?(categories(:child_2))
- assert !categories(:child_1).is_or_is_ancestor_of?(categories(:child_2))
- assert categories(:child_1).is_or_is_ancestor_of?(categories(:child_1))
- end
-
- def test_is_ancestor_of?
- assert categories(:top_level).is_ancestor_of?(categories(:child_1))
- assert categories(:top_level).is_ancestor_of?(categories(:child_2_1))
- assert categories(:child_2).is_ancestor_of?(categories(:child_2_1))
- assert !categories(:child_2_1).is_ancestor_of?(categories(:child_2))
- assert !categories(:child_1).is_ancestor_of?(categories(:child_2))
- assert !categories(:child_1).is_ancestor_of?(categories(:child_1))
- end
-
- def test_is_or_is_ancestor_of_with_scope
- root = Scoped.root
- child = root.children.first
- assert root.is_or_is_ancestor_of?(child)
- child.update_attribute :organization_id, 'different'
- assert !root.is_or_is_ancestor_of?(child)
- end
-
- def test_is_or_is_descendant_of?
- assert categories(:child_1).is_or_is_descendant_of?(categories(:top_level))
- assert categories(:child_2_1).is_or_is_descendant_of?(categories(:top_level))
- assert categories(:child_2_1).is_or_is_descendant_of?(categories(:child_2))
- assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_2_1))
- assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_1))
- assert categories(:child_1).is_or_is_descendant_of?(categories(:child_1))
- end
-
- def test_is_descendant_of?
- assert categories(:child_1).is_descendant_of?(categories(:top_level))
- assert categories(:child_2_1).is_descendant_of?(categories(:top_level))
- assert categories(:child_2_1).is_descendant_of?(categories(:child_2))
- assert !categories(:child_2).is_descendant_of?(categories(:child_2_1))
- assert !categories(:child_2).is_descendant_of?(categories(:child_1))
- assert !categories(:child_1).is_descendant_of?(categories(:child_1))
- end
-
- def test_is_or_is_descendant_of_with_scope
- root = Scoped.root
- child = root.children.first
- assert child.is_or_is_descendant_of?(root)
- child.update_attribute :organization_id, 'different'
- assert !child.is_or_is_descendant_of?(root)
- end
-
- def test_same_scope?
- root = Scoped.root
- child = root.children.first
- assert child.same_scope?(root)
- child.update_attribute :organization_id, 'different'
- assert !child.same_scope?(root)
- end
-
- def test_left_sibling
- assert_equal categories(:child_1), categories(:child_2).left_sibling
- assert_equal categories(:child_2), categories(:child_3).left_sibling
- end
-
- def test_left_sibling_of_root
- assert_nil categories(:top_level).left_sibling
- end
-
- def test_left_sibling_without_siblings
- assert_nil categories(:child_2_1).left_sibling
- end
-
- def test_left_sibling_of_leftmost_node
- assert_nil categories(:child_1).left_sibling
- end
-
- def test_right_sibling
- assert_equal categories(:child_3), categories(:child_2).right_sibling
- assert_equal categories(:child_2), categories(:child_1).right_sibling
- end
-
- def test_right_sibling_of_root
- assert_equal categories(:top_level_2), categories(:top_level).right_sibling
- assert_nil categories(:top_level_2).right_sibling
- end
-
- def test_right_sibling_without_siblings
- assert_nil categories(:child_2_1).right_sibling
- end
-
- def test_right_sibling_of_rightmost_node
- assert_nil categories(:child_3).right_sibling
- end
-
- def test_move_left
- categories(:child_2).move_left
- assert_nil categories(:child_2).left_sibling
- assert_equal categories(:child_1), categories(:child_2).right_sibling
- assert Category.valid?
- end
-
- def test_move_right
- categories(:child_2).move_right
- assert_nil categories(:child_2).right_sibling
- assert_equal categories(:child_3), categories(:child_2).left_sibling
- assert Category.valid?
- end
-
- def test_move_to_left_of
- categories(:child_3).move_to_left_of(categories(:child_1))
- assert_nil categories(:child_3).left_sibling
- assert_equal categories(:child_1), categories(:child_3).right_sibling
- assert Category.valid?
- end
-
- def test_move_to_right_of
- categories(:child_1).move_to_right_of(categories(:child_3))
- assert_nil categories(:child_1).right_sibling
- assert_equal categories(:child_3), categories(:child_1).left_sibling
- assert Category.valid?
- end
-
- def test_move_to_root
- categories(:child_2).move_to_root
- assert_nil categories(:child_2).parent
- assert_equal 0, categories(:child_2).level
- assert_equal 1, categories(:child_2_1).level
- assert_equal 1, categories(:child_2).left
- assert_equal 4, categories(:child_2).right
- assert Category.valid?
- end
-
- def test_move_to_child_of
- categories(:child_1).move_to_child_of(categories(:child_3))
- assert_equal categories(:child_3).id, categories(:child_1).parent_id
- assert Category.valid?
- end
-
- def test_move_to_child_of_appends_to_end
- child = Category.create! :name => 'New Child'
- child.move_to_child_of categories(:top_level)
- assert_equal child, categories(:top_level).children.last
- end
-
- def test_subtree_move_to_child_of
- assert_equal 4, categories(:child_2).left
- assert_equal 7, categories(:child_2).right
-
- assert_equal 2, categories(:child_1).left
- assert_equal 3, categories(:child_1).right
-
- categories(:child_2).move_to_child_of(categories(:child_1))
- assert Category.valid?
- assert_equal categories(:child_1).id, categories(:child_2).parent_id
-
- assert_equal 3, categories(:child_2).left
- assert_equal 6, categories(:child_2).right
- assert_equal 2, categories(:child_1).left
- assert_equal 7, categories(:child_1).right
- end
-
- def test_slightly_difficult_move_to_child_of
- assert_equal 11, categories(:top_level_2).left
- assert_equal 12, categories(:top_level_2).right
-
- # create a new top-level node and move single-node top-level tree inside it.
- new_top = Category.create(:name => 'New Top')
- assert_equal 13, new_top.left
- assert_equal 14, new_top.right
-
- categories(:top_level_2).move_to_child_of(new_top)
-
- assert Category.valid?
- assert_equal new_top.id, categories(:top_level_2).parent_id
-
- assert_equal 12, categories(:top_level_2).left
- assert_equal 13, categories(:top_level_2).right
- assert_equal 11, new_top.left
- assert_equal 14, new_top.right
- end
-
- def test_difficult_move_to_child_of
- assert_equal 1, categories(:top_level).left
- assert_equal 10, categories(:top_level).right
- assert_equal 5, categories(:child_2_1).left
- assert_equal 6, categories(:child_2_1).right
-
- # create a new top-level node and move an entire top-level tree inside it.
- new_top = Category.create(:name => 'New Top')
- categories(:top_level).move_to_child_of(new_top)
- categories(:child_2_1).reload
- assert Category.valid?
- assert_equal new_top.id, categories(:top_level).parent_id
-
- assert_equal 4, categories(:top_level).left
- assert_equal 13, categories(:top_level).right
- assert_equal 8, categories(:child_2_1).left
- assert_equal 9, categories(:child_2_1).right
- end
-
- #rebuild swaps the position of the 2 children when added using move_to_child twice onto same parent
- def test_move_to_child_more_than_once_per_parent_rebuild
- root1 = Category.create(:name => 'Root1')
- root2 = Category.create(:name => 'Root2')
- root3 = Category.create(:name => 'Root3')
-
- root2.move_to_child_of root1
- root3.move_to_child_of root1
-
- output = Category.roots.last.to_text
- Category.update_all('lft = null, rgt = null')
- Category.rebuild!
-
- assert_equal Category.roots.last.to_text, output
- end
-
- # doing move_to_child twice onto same parent from the furthest right first
- def test_move_to_child_more_than_once_per_parent_outside_in
- node1 = Category.create(:name => 'Node-1')
- node2 = Category.create(:name => 'Node-2')
- node3 = Category.create(:name => 'Node-3')
-
- node2.move_to_child_of node1
- node3.move_to_child_of node1
-
- output = Category.roots.last.to_text
- Category.update_all('lft = null, rgt = null')
- Category.rebuild!
-
- assert_equal Category.roots.last.to_text, output
- end
-
-
- def test_valid_with_null_lefts
- assert Category.valid?
- Category.update_all('lft = null')
- assert !Category.valid?
- end
-
- def test_valid_with_null_rights
- assert Category.valid?
- Category.update_all('rgt = null')
- assert !Category.valid?
- end
-
- def test_valid_with_missing_intermediate_node
- # Even though child_2_1 will still exist, it is a sign of a sloppy delete, not an invalid tree.
- assert Category.valid?
- Category.delete(categories(:child_2).id)
- assert Category.valid?
- end
-
- def test_valid_with_overlapping_and_rights
- assert Category.valid?
- categories(:top_level_2)['lft'] = 0
- categories(:top_level_2).save
- assert !Category.valid?
- end
-
- def test_rebuild
- assert Category.valid?
- before_text = Category.root.to_text
- Category.update_all('lft = null, rgt = null')
- Category.rebuild!
- assert Category.valid?
- assert_equal before_text, Category.root.to_text
- end
-
- def test_move_possible_for_sibling
- assert categories(:child_2).move_possible?(categories(:child_1))
- end
-
- def test_move_not_possible_to_self
- assert !categories(:top_level).move_possible?(categories(:top_level))
- end
-
- def test_move_not_possible_to_parent
- categories(:top_level).descendants.each do |descendant|
- assert !categories(:top_level).move_possible?(descendant)
- assert descendant.move_possible?(categories(:top_level))
- end
- end
-
- def test_is_or_is_ancestor_of?
- [:child_1, :child_2, :child_2_1, :child_3].each do |c|
- assert categories(:top_level).is_or_is_ancestor_of?(categories(c))
- end
- assert !categories(:top_level).is_or_is_ancestor_of?(categories(:top_level_2))
- end
-
- def test_left_and_rights_valid_with_blank_left
- assert Category.left_and_rights_valid?
- categories(:child_2)[:lft] = nil
- categories(:child_2).save(false)
- assert !Category.left_and_rights_valid?
- end
-
- def test_left_and_rights_valid_with_blank_right
- assert Category.left_and_rights_valid?
- categories(:child_2)[:rgt] = nil
- categories(:child_2).save(false)
- assert !Category.left_and_rights_valid?
- end
-
- def test_left_and_rights_valid_with_equal
- assert Category.left_and_rights_valid?
- categories(:top_level_2)[:lft] = categories(:top_level_2)[:rgt]
- categories(:top_level_2).save(false)
- assert !Category.left_and_rights_valid?
- end
-
- def test_left_and_rights_valid_with_left_equal_to_parent
- assert Category.left_and_rights_valid?
- categories(:child_2)[:lft] = categories(:top_level)[:lft]
- categories(:child_2).save(false)
- assert !Category.left_and_rights_valid?
- end
-
- def test_left_and_rights_valid_with_right_equal_to_parent
- assert Category.left_and_rights_valid?
- categories(:child_2)[:rgt] = categories(:top_level)[:rgt]
- categories(:child_2).save(false)
- assert !Category.left_and_rights_valid?
- end
-
- def test_moving_dirty_objects_doesnt_invalidate_tree
- r1 = Category.create
- r2 = Category.create
- r3 = Category.create
- r4 = Category.create
- nodes = [r1, r2, r3, r4]
-
- r2.move_to_child_of(r1)
- assert Category.valid?
-
- r3.move_to_child_of(r1)
- assert Category.valid?
-
- r4.move_to_child_of(r2)
- assert Category.valid?
- end
-
- def test_multi_scoped_no_duplicates_for_columns?
- assert_nothing_raised do
- Note.no_duplicates_for_columns?
- end
- end
-
- def test_multi_scoped_all_roots_valid?
- assert_nothing_raised do
- Note.all_roots_valid?
- end
- end
-
- def test_multi_scoped
- note1 = Note.create!(:body => "A", :notable_id => 2, :notable_type => 'Category')
- note2 = Note.create!(:body => "B", :notable_id => 2, :notable_type => 'Category')
- note3 = Note.create!(:body => "C", :notable_id => 2, :notable_type => 'Default')
-
- assert_equal [note1, note2], note1.self_and_siblings
- assert_equal [note3], note3.self_and_siblings
- end
-
- def test_multi_scoped_rebuild
- root = Note.create!(:body => "A", :notable_id => 3, :notable_type => 'Category')
- child1 = Note.create!(:body => "B", :notable_id => 3, :notable_type => 'Category')
- child2 = Note.create!(:body => "C", :notable_id => 3, :notable_type => 'Category')
-
- child1.move_to_child_of root
- child2.move_to_child_of root
-
- Note.update_all('lft = null, rgt = null')
- Note.rebuild!
-
- assert_equal Note.roots.find_by_body('A'), root
- assert_equal [child1, child2], Note.roots.find_by_body('A').children
- end
-
- def test_same_scope_with_multi_scopes
- assert_nothing_raised do
- notes(:scope1).same_scope?(notes(:child_1))
- end
- assert notes(:scope1).same_scope?(notes(:child_1))
- assert notes(:child_1).same_scope?(notes(:scope1))
- assert !notes(:scope1).same_scope?(notes(:scope2))
- end
-
- def test_quoting_of_multi_scope_column_names
- assert_equal ["\"notable_id\"", "\"notable_type\""], Note.quoted_scope_column_names
- end
-
- def test_equal_in_same_scope
- assert_equal notes(:scope1), notes(:scope1)
- assert_not_equal notes(:scope1), notes(:child_1)
- end
-
- def test_equal_in_different_scopes
- assert_not_equal notes(:scope1), notes(:scope2)
- end
-
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/test/db/database.yml b/trustie2/lib/plugins/awesome_nested_set/test/db/database.yml
deleted file mode 100644
index 9281236d2..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/test/db/database.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-sqlite3:
- adapter: sqlite3
- dbfile: awesome_nested_set.sqlite3.db
-sqlite3mem:
- :adapter: sqlite3
- :dbfile: ":memory:"
-postgresql:
- :adapter: postgresql
- :username: postgres
- :password: postgres
- :database: awesome_nested_set_plugin_test
- :min_messages: ERROR
-mysql:
- :adapter: mysql
- :host: localhost
- :username: root
- :password:
- :database: awesome_nested_set_plugin_test
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/test/db/schema.rb b/trustie2/lib/plugins/awesome_nested_set/test/db/schema.rb
deleted file mode 100644
index bbed1eb16..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/test/db/schema.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-ActiveRecord::Schema.define(:version => 0) do
-
- create_table :categories, :force => true do |t|
- t.column :name, :string
- t.column :parent_id, :integer
- t.column :lft, :integer
- t.column :rgt, :integer
- t.column :organization_id, :integer
- end
-
- create_table :departments, :force => true do |t|
- t.column :name, :string
- end
-
- create_table :notes, :force => true do |t|
- t.column :body, :text
- t.column :parent_id, :integer
- t.column :lft, :integer
- t.column :rgt, :integer
- t.column :notable_id, :integer
- t.column :notable_type, :string
- end
-end
diff --git a/trustie2/lib/plugins/awesome_nested_set/test/fixtures/categories.yml b/trustie2/lib/plugins/awesome_nested_set/test/fixtures/categories.yml
deleted file mode 100644
index bc8e078e8..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/test/fixtures/categories.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-top_level:
- id: 1
- name: Top Level
- lft: 1
- rgt: 10
-child_1:
- id: 2
- name: Child 1
- parent_id: 1
- lft: 2
- rgt: 3
-child_2:
- id: 3
- name: Child 2
- parent_id: 1
- lft: 4
- rgt: 7
-child_2_1:
- id: 4
- name: Child 2.1
- parent_id: 3
- lft: 5
- rgt: 6
-child_3:
- id: 5
- name: Child 3
- parent_id: 1
- lft: 8
- rgt: 9
-top_level_2:
- id: 6
- name: Top Level 2
- lft: 11
- rgt: 12
diff --git a/trustie2/lib/plugins/awesome_nested_set/test/fixtures/category.rb b/trustie2/lib/plugins/awesome_nested_set/test/fixtures/category.rb
deleted file mode 100644
index 506b0dac5..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/test/fixtures/category.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class Category < ActiveRecord::Base
- acts_as_nested_set
-
- def to_s
- name
- end
-
- def recurse &block
- block.call self, lambda{
- self.children.each do |child|
- child.recurse &block
- end
- }
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/test/fixtures/departments.yml b/trustie2/lib/plugins/awesome_nested_set/test/fixtures/departments.yml
deleted file mode 100644
index e50a944f1..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/test/fixtures/departments.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-top:
- id: 1
- name: Top
\ No newline at end of file
diff --git a/trustie2/lib/plugins/awesome_nested_set/test/fixtures/notes.yml b/trustie2/lib/plugins/awesome_nested_set/test/fixtures/notes.yml
deleted file mode 100644
index 004a5335a..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/test/fixtures/notes.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-scope1:
- id: 1
- body: Top Level
- lft: 1
- rgt: 10
- notable_id: 1
- notable_type: Category
-child_1:
- id: 2
- body: Child 1
- parent_id: 1
- lft: 2
- rgt: 3
- notable_id: 1
- notable_type: Category
-child_2:
- id: 3
- body: Child 2
- parent_id: 1
- lft: 4
- rgt: 7
- notable_id: 1
- notable_type: Category
-child_3:
- id: 4
- body: Child 3
- parent_id: 1
- lft: 8
- rgt: 9
- notable_id: 1
- notable_type: Category
-scope2:
- id: 5
- body: Top Level 2
- lft: 1
- rgt: 2
- notable_id: 1
- notable_type: Departments
diff --git a/trustie2/lib/plugins/awesome_nested_set/test/test_helper.rb b/trustie2/lib/plugins/awesome_nested_set/test/test_helper.rb
deleted file mode 100644
index 693982236..000000000
--- a/trustie2/lib/plugins/awesome_nested_set/test/test_helper.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-$:.unshift(File.dirname(__FILE__) + '/../lib')
-plugin_test_dir = File.dirname(__FILE__)
-
-require 'rubygems'
-require 'test/unit'
-require 'multi_rails_init'
-# gem 'activerecord', '>= 2.0'
-require 'active_record'
-require 'action_controller'
-require 'action_view'
-require 'active_record/fixtures'
-
-require plugin_test_dir + '/../init.rb'
-
-ActiveRecord::Base.logger = Logger.new(plugin_test_dir + "/debug.log")
-
-ActiveRecord::Base.configurations = YAML::load(IO.read(plugin_test_dir + "/db/database.yml"))
-ActiveRecord::Base.establish_connection(ENV["DB"] || "sqlite3mem")
-ActiveRecord::Migration.verbose = false
-load(File.join(plugin_test_dir, "db", "schema.rb"))
-
-Dir["#{plugin_test_dir}/fixtures/*.rb"].each {|file| require file }
-
-
-class Test::Unit::TestCase #:nodoc:
- self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
- self.use_transactional_fixtures = true
- self.use_instantiated_fixtures = false
-
- fixtures :categories, :notes, :departments
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/gravatar/.gitignore b/trustie2/lib/plugins/gravatar/.gitignore
deleted file mode 100644
index 4ebc8aea5..000000000
--- a/trustie2/lib/plugins/gravatar/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-coverage
diff --git a/trustie2/lib/plugins/gravatar/MIT-LICENSE b/trustie2/lib/plugins/gravatar/MIT-LICENSE
deleted file mode 100644
index c3963ce0c..000000000
--- a/trustie2/lib/plugins/gravatar/MIT-LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) 2007 West Arete Computing, Inc.
-
-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, title 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.
\ No newline at end of file
diff --git a/trustie2/lib/plugins/gravatar/README.rdoc b/trustie2/lib/plugins/gravatar/README.rdoc
deleted file mode 100644
index 0b95e85e8..000000000
--- a/trustie2/lib/plugins/gravatar/README.rdoc
+++ /dev/null
@@ -1,55 +0,0 @@
-== Gravatar Plugin
-
-This plugin provides a handful of view helpers for displaying gravatars
-(globally-recognized avatars).
-
-Gravatars allow users to configure an avatar to go with their email address at
-a central location: http://gravatar.com. Gravatar-aware websites (such
-as yours) can then look up and display each user's preferred avatar, without
-having to handle avatar management. The user gets the benefit of not having to
-set up an avatar for each site that they post on.
-
-== Installation
-
- cd ~/myapp
- ruby script/plugin install git://github.com/woods/gravatar-plugin.git
-
-or, if you're using piston[http://piston.rubyforge.org] (worth it!):
-
- cd ~/myapp/vendor/plugins
- piston import git://github.com/woods/gravatar-plugin.git
-
-== Example
-
-If you represent your users with a model that has an +email+ method (typical
-for most rails authentication setups), then you can simply use this method
-in your views:
-
- <%= gravatar_for @user %>
-
-This will be replaced with the full HTML +img+ tag necessary for displaying
-that user's gravatar.
-
-Other helpers are documented under GravatarHelper::PublicMethods.
-
-== Acknowledgments
-
-Thanks to Magnus Bergmark (http://github.com/Mange), who contributed the SSL
-support in this plugin, as well as a few minor fixes.
-
-The following people have also written gravatar-related Ruby libraries:
-* Seth Rasmussen created the gravatar gem[http://gravatar.rubyforge.org]
-* Matt McCray has also created a gravatar
- plugin[http://mattmccray.com/svn/rails/plugins/gravatar_helper]
-
-== Author
-
- Scott A. Woods
- West Arete Computing, Inc.
- http://westarete.com
- scott at westarete dot com
-
-== TODO
-
-* Add specs for ssl support
-* Finish rdoc documentation
\ No newline at end of file
diff --git a/trustie2/lib/plugins/gravatar/Rakefile b/trustie2/lib/plugins/gravatar/Rakefile
deleted file mode 100644
index e67e5e7f9..000000000
--- a/trustie2/lib/plugins/gravatar/Rakefile
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'spec/rake/spectask'
-require 'rake/rdoctask'
-
-desc 'Default: run all specs'
-task :default => :spec
-
-desc 'Run all application-specific specs'
-Spec::Rake::SpecTask.new(:spec) do |t|
- # t.rcov = true
-end
-
-desc "Report code statistics (KLOCs, etc) from the application"
-task :stats do
- RAILS_ROOT = File.dirname(__FILE__)
- STATS_DIRECTORIES = [
- %w(Libraries lib/),
- %w(Specs spec/),
- ].collect { |name, dir| [ name, "#{RAILS_ROOT}/#{dir}" ] }.select { |name, dir| File.directory?(dir) }
- require 'code_statistics'
- CodeStatistics.new(*STATS_DIRECTORIES).to_s
-end
-
-namespace :doc do
- desc 'Generate documentation for the assert_request plugin.'
- Rake::RDocTask.new(:plugin) do |rdoc|
- rdoc.rdoc_dir = 'rdoc'
- rdoc.title = 'Gravatar Rails Plugin'
- rdoc.options << '--line-numbers' << '--inline-source' << '--accessor' << 'cattr_accessor=rw'
- rdoc.rdoc_files.include('README')
- rdoc.rdoc_files.include('lib/**/*.rb')
- end
-end
diff --git a/trustie2/lib/plugins/gravatar/about.yml b/trustie2/lib/plugins/gravatar/about.yml
deleted file mode 100644
index aa5b8b19d..000000000
--- a/trustie2/lib/plugins/gravatar/about.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-author: Scott Woods, West Arete Computing
-summary: View helpers for displaying gravatars.
-homepage: http://github.com/woods/gravatar-plugin/
-plugin: git://github.com/woods/gravatar-plugin.git
-license: MIT
-version: 0.1
-rails_version: 1.0+
diff --git a/trustie2/lib/plugins/gravatar/init.rb b/trustie2/lib/plugins/gravatar/init.rb
deleted file mode 100644
index aab3f75f3..000000000
--- a/trustie2/lib/plugins/gravatar/init.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'gravatar'
-ActionView::Base.send :include, GravatarHelper::PublicMethods
diff --git a/trustie2/lib/plugins/gravatar/lib/gravatar.rb b/trustie2/lib/plugins/gravatar/lib/gravatar.rb
deleted file mode 100644
index a0b1241b2..000000000
--- a/trustie2/lib/plugins/gravatar/lib/gravatar.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-require 'digest/md5'
-require 'cgi'
-
-module GravatarHelper
-
- # These are the options that control the default behavior of the public
- # methods. They can be overridden during the actual call to the helper,
- # or you can set them in your environment.rb as such:
- #
- # # Allow racier gravatars
- # GravatarHelper::DEFAULT_OPTIONS[:rating] = 'R'
- #
- DEFAULT_OPTIONS = {
- # The URL of a default image to display if the given email address does
- # not have a gravatar.
- :default => nil,
-
- # The default size in pixels for the gravatar image (they're square).
- :size => 50,
-
- # The maximum allowed MPAA rating for gravatars. This allows you to
- # exclude gravatars that may be out of character for your site.
- :rating => 'PG',
-
- # The alt text to use in the img tag for the gravatar. Since it's a
- # decorational picture, the alt text should be empty according to the
- # XHTML specs.
- :alt => '',
-
- # The title text to use for the img tag for the gravatar.
- :title => '',
-
- # The class to assign to the img tag for the gravatar.
- :class => 'gravatar',
-
- # Whether or not to display the gravatars using HTTPS instead of HTTP
- :ssl => false,
- }
-
- # The methods that will be made available to your views.
- module PublicMethods
-
- # Return the HTML img tag for the given user's gravatar. Presumes that
- # the given user object will respond_to "email", and return the user's
- # email address.
- def gravatar_for(user, options={})
- gravatar(user.email, options)
- end
-
- # Return the HTML img tag for the given email address's gravatar.
- def gravatar(email, options={})
- src = h(gravatar_url(email, options))
- options = DEFAULT_OPTIONS.merge(options)
- [:class, :alt, :title].each { |opt| options[opt] = h(options[opt]) }
- image_tag src, options
- end
-
- # Returns the base Gravatar URL for the given email hash. If ssl evaluates to true,
- # a secure URL will be used instead. This is required when the gravatar is to be
- # displayed on a HTTPS site.
- def gravatar_api_url(hash, ssl=false)
- if ssl
- "https://secure.gravatar.com/avatar/#{hash}"
- else
- "http://www.gravatar.com/avatar/#{hash}"
- end
- end
-
- # Return the gravatar URL for the given email address.
- def gravatar_url(email, options={})
- email_hash = Digest::MD5.hexdigest(email)
- options = DEFAULT_OPTIONS.merge(options)
- options[:default] = CGI::escape(options[:default]) unless options[:default].nil?
- gravatar_api_url(email_hash, options.delete(:ssl)).tap do |url|
- opts = []
- [:rating, :size, :default].each do |opt|
- unless options[opt].nil?
- value = h(options[opt])
- opts << [opt, value].join('=')
- end
- end
- url << "?#{opts.join('&')}" unless opts.empty?
- end
- end
-
- end
-
-end
diff --git a/trustie2/lib/plugins/gravatar/spec/gravatar_spec.rb b/trustie2/lib/plugins/gravatar/spec/gravatar_spec.rb
deleted file mode 100644
index 6f78d79ad..000000000
--- a/trustie2/lib/plugins/gravatar/spec/gravatar_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-require 'rubygems'
-require 'erb' # to get "h"
-require 'active_support' # to get "returning"
-require File.dirname(__FILE__) + '/../lib/gravatar'
-include GravatarHelper, GravatarHelper::PublicMethods, ERB::Util
-
-describe "gravatar_url with a custom default URL" do
- before(:each) do
- @original_options = DEFAULT_OPTIONS.dup
- DEFAULT_OPTIONS[:default] = "no_avatar.png"
- @url = gravatar_url("somewhere")
- end
-
- it "should include the \"default\" argument in the result" do
- @url.should match(/&default=no_avatar.png/)
- end
-
- after(:each) do
- DEFAULT_OPTIONS.merge!(@original_options)
- end
-
-end
-
-describe "gravatar_url with default settings" do
- before(:each) do
- @url = gravatar_url("somewhere")
- end
-
- it "should have a nil default URL" do
- DEFAULT_OPTIONS[:default].should be_nil
- end
-
- it "should not include the \"default\" argument in the result" do
- @url.should_not match(/&default=/)
- end
-
-end
-
-describe "gravatar with a custom title option" do
- it "should include the title in the result" do
- gravatar('example@example.com', :title => "This is a title attribute").should match(/This is a title attribute/)
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/CHANGELOG b/trustie2/lib/plugins/open_id_authentication/CHANGELOG
deleted file mode 100644
index 0c8971efd..000000000
--- a/trustie2/lib/plugins/open_id_authentication/CHANGELOG
+++ /dev/null
@@ -1,37 +0,0 @@
-* Dump heavy lifting off to rack-openid gem. OpenIdAuthentication is just a simple controller concern.
-
-* Fake HTTP method from OpenID server since they only support a GET. Eliminates the need to set an extra route to match the server's reply. [Josh Peek]
-
-* OpenID 2.0 recommends that forms should use the field name "openid_identifier" rather than "openid_url" [Josh Peek]
-
-* Return open_id_response.display_identifier to the application instead of .endpoints.claimed_id. [nbibler]
-
-* Add Timeout protection [Rick]
-
-* An invalid identity url passed through authenticate_with_open_id will no longer raise an InvalidOpenId exception. Instead it will return Result[:missing] to the completion block.
-
-* Allow a return_to option to be used instead of the requested url [Josh Peek]
-
-* Updated plugin to use Ruby OpenID 2.x.x [Josh Peek]
-
-* Tied plugin to ruby-openid 1.1.4 gem until we can make it compatible with 2.x [DHH]
-
-* Use URI instead of regexps to normalize the URL and gain free, better matching #8136 [dkubb]
-
-* Allow -'s in #normalize_url [Rick]
-
-* remove instance of mattr_accessor, it was breaking tests since they don't load ActiveSupport. Fix Timeout test [Rick]
-
-* Throw a InvalidOpenId exception instead of just a RuntimeError when the URL can't be normalized [DHH]
-
-* Just use the path for the return URL, so extra query parameters don't interfere [DHH]
-
-* Added a new default database-backed store after experiencing trouble with the filestore on NFS. The file store is still available as an option [DHH]
-
-* Added normalize_url and applied it to all operations going through the plugin [DHH]
-
-* Removed open_id? as the idea of using the same input box for both OpenID and username has died -- use using_open_id? instead (which checks for the presence of params[:openid_url] by default) [DHH]
-
-* Added OpenIdAuthentication::Result to make it easier to deal with default situations where you don't care to do something particular for each error state [DHH]
-
-* Stop relying on root_url being defined, we can just grab the current url instead [DHH]
\ No newline at end of file
diff --git a/trustie2/lib/plugins/open_id_authentication/README b/trustie2/lib/plugins/open_id_authentication/README
deleted file mode 100644
index fe2b37e29..000000000
--- a/trustie2/lib/plugins/open_id_authentication/README
+++ /dev/null
@@ -1,223 +0,0 @@
-OpenIdAuthentication
-====================
-
-Provides a thin wrapper around the excellent ruby-openid gem from JanRan. Be sure to install that first:
-
- gem install ruby-openid
-
-To understand what OpenID is about and how it works, it helps to read the documentation for lib/openid/consumer.rb
-from that gem.
-
-The specification used is http://openid.net/specs/openid-authentication-2_0.html.
-
-
-Prerequisites
-=============
-
-OpenID authentication uses the session, so be sure that you haven't turned that off.
-
-Alternatively, you can use the file-based store, which just relies on on tmp/openids being present in RAILS_ROOT. But be aware that this store only works if you have a single application server. And it's not safe to use across NFS. It's recommended that you use the database store if at all possible. To use the file-based store, you'll also have to add this line to your config/environment.rb:
-
- OpenIdAuthentication.store = :file
-
-This particular plugin also relies on the fact that the authentication action allows for both POST and GET operations.
-If you're using RESTful authentication, you'll need to explicitly allow for this in your routes.rb.
-
-The plugin also expects to find a root_url method that points to the home page of your site. You can accomplish this by using a root route in config/routes.rb:
-
- map.root :controller => 'articles'
-
-This plugin relies on Rails Edge revision 6317 or newer.
-
-
-Example
-=======
-
-This example is just to meant to demonstrate how you could use OpenID authentication. You might well want to add
-salted hash logins instead of plain text passwords and other requirements on top of this. Treat it as a starting point,
-not a destination.
-
-Note that the User model referenced in the simple example below has an 'identity_url' attribute. You will want to add the same or similar field to whatever
-model you are using for authentication.
-
-Also of note is the following code block used in the example below:
-
- authenticate_with_open_id do |result, identity_url|
- ...
- end
-
-In the above code block, 'identity_url' will need to match user.identity_url exactly. 'identity_url' will be a string in the form of 'http://example.com' -
-If you are storing just 'example.com' with your user, the lookup will fail.
-
-There is a handy method in this plugin called 'normalize_url' that will help with validating OpenID URLs.
-
- OpenIdAuthentication.normalize_url(user.identity_url)
-
-The above will return a standardized version of the OpenID URL - the above called with 'example.com' will return 'http://example.com/'
-It will also raise an InvalidOpenId exception if the URL is determined to not be valid.
-Use the above code in your User model and validate OpenID URLs before saving them.
-
-config/routes.rb
-
- map.root :controller => 'articles'
- map.resource :session
-
-
-app/views/sessions/new.erb
-
- <% form_tag(session_url) do %>
-
-
- <%= text_field_tag "name" %>
-
-
-
-
- <%= password_field_tag %>
-
-
-
- ...or use:
-
-
-
-
- <%= text_field_tag "openid_identifier" %>
-
-
-
- <%= submit_tag 'Sign in', :disable_with => "Signing in…" %>
-
- <% end %>
-
-app/controllers/sessions_controller.rb
- class SessionsController < ApplicationController
- def create
- if using_open_id?
- open_id_authentication
- else
- password_authentication(params[:name], params[:password])
- end
- end
-
-
- protected
- def password_authentication(name, password)
- if @current_user = @account.users.authenticate(params[:name], params[:password])
- successful_login
- else
- failed_login "Sorry, that username/password doesn't work"
- end
- end
-
- def open_id_authentication
- authenticate_with_open_id do |result, identity_url|
- if result.successful?
- if @current_user = @account.users.find_by_identity_url(identity_url)
- successful_login
- else
- failed_login "Sorry, no user by that identity URL exists (#{identity_url})"
- end
- else
- failed_login result.message
- end
- end
- end
-
-
- private
- def successful_login
- session[:user_id] = @current_user.id
- redirect_to(root_url)
- end
-
- def failed_login(message)
- flash[:error] = message
- redirect_to(new_session_url)
- end
- end
-
-
-
-If you're fine with the result messages above and don't need individual logic on a per-failure basis,
-you can collapse the case into a mere boolean:
-
- def open_id_authentication
- authenticate_with_open_id do |result, identity_url|
- if result.successful? && @current_user = @account.users.find_by_identity_url(identity_url)
- successful_login
- else
- failed_login(result.message || "Sorry, no user by that identity URL exists (#{identity_url})")
- end
- end
- end
-
-
-Simple Registration OpenID Extension
-====================================
-
-Some OpenID Providers support this lightweight profile exchange protocol. See more: http://www.openidenabled.com/openid/simple-registration-extension
-
-You can support it in your app by changing #open_id_authentication
-
- def open_id_authentication(identity_url)
- # Pass optional :required and :optional keys to specify what sreg fields you want.
- # Be sure to yield registration, a third argument in the #authenticate_with_open_id block.
- authenticate_with_open_id(identity_url,
- :required => [ :nickname, :email ],
- :optional => :fullname) do |result, identity_url, registration|
- case result.status
- when :missing
- failed_login "Sorry, the OpenID server couldn't be found"
- when :invalid
- failed_login "Sorry, but this does not appear to be a valid OpenID"
- when :canceled
- failed_login "OpenID verification was canceled"
- when :failed
- failed_login "Sorry, the OpenID verification failed"
- when :successful
- if @current_user = @account.users.find_by_identity_url(identity_url)
- assign_registration_attributes!(registration)
-
- if current_user.save
- successful_login
- else
- failed_login "Your OpenID profile registration failed: " +
- @current_user.errors.full_messages.to_sentence
- end
- else
- failed_login "Sorry, no user by that identity URL exists"
- end
- end
- end
- end
-
- # registration is a hash containing the valid sreg keys given above
- # use this to map them to fields of your user model
- def assign_registration_attributes!(registration)
- model_to_registration_mapping.each do |model_attribute, registration_attribute|
- unless registration[registration_attribute].blank?
- @current_user.send("#{model_attribute}=", registration[registration_attribute])
- end
- end
- end
-
- def model_to_registration_mapping
- { :login => 'nickname', :email => 'email', :display_name => 'fullname' }
- end
-
-Attribute Exchange OpenID Extension
-===================================
-
-Some OpenID providers also support the OpenID AX (attribute exchange) protocol for exchanging identity information between endpoints. See more: http://openid.net/specs/openid-attribute-exchange-1_0.html
-
-Accessing AX data is very similar to the Simple Registration process, described above -- just add the URI identifier for the AX field to your :optional or :required parameters. For example:
-
- authenticate_with_open_id(identity_url,
- :required => [ :email, 'http://schema.openid.net/birthDate' ]) do |result, identity_url, registration|
-
-This would provide the sreg data for :email, and the AX data for 'http://schema.openid.net/birthDate'
-
-
-
-Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
\ No newline at end of file
diff --git a/trustie2/lib/plugins/open_id_authentication/Rakefile b/trustie2/lib/plugins/open_id_authentication/Rakefile
deleted file mode 100644
index 31074b856..000000000
--- a/trustie2/lib/plugins/open_id_authentication/Rakefile
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'rake'
-require 'rake/testtask'
-require 'rake/rdoctask'
-
-desc 'Default: run unit tests.'
-task :default => :test
-
-desc 'Test the open_id_authentication plugin.'
-Rake::TestTask.new(:test) do |t|
- t.libs << 'lib'
- t.pattern = 'test/**/*_test.rb'
- t.verbose = true
-end
-
-desc 'Generate documentation for the open_id_authentication plugin.'
-Rake::RDocTask.new(:rdoc) do |rdoc|
- rdoc.rdoc_dir = 'rdoc'
- rdoc.title = 'OpenIdAuthentication'
- rdoc.options << '--line-numbers' << '--inline-source'
- rdoc.rdoc_files.include('README')
- rdoc.rdoc_files.include('lib/**/*.rb')
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/generators/open_id_authentication_tables/open_id_authentication_tables_generator.rb b/trustie2/lib/plugins/open_id_authentication/generators/open_id_authentication_tables/open_id_authentication_tables_generator.rb
deleted file mode 100644
index 6f78afc71..000000000
--- a/trustie2/lib/plugins/open_id_authentication/generators/open_id_authentication_tables/open_id_authentication_tables_generator.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class OpenIdAuthenticationTablesGenerator < Rails::Generator::NamedBase
- def initialize(runtime_args, runtime_options = {})
- super
- end
-
- def manifest
- record do |m|
- m.migration_template 'migration.rb', 'db/migrate'
- end
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/generators/open_id_authentication_tables/templates/migration.rb b/trustie2/lib/plugins/open_id_authentication/generators/open_id_authentication_tables/templates/migration.rb
deleted file mode 100644
index ef2a0cfb4..000000000
--- a/trustie2/lib/plugins/open_id_authentication/generators/open_id_authentication_tables/templates/migration.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-class <%= class_name %> < ActiveRecord::Migration
- def self.up
- create_table :open_id_authentication_associations, :force => true do |t|
- t.integer :issued, :lifetime
- t.string :handle, :assoc_type
- t.binary :server_url, :secret
- end
-
- create_table :open_id_authentication_nonces, :force => true do |t|
- t.integer :timestamp, :null => false
- t.string :server_url, :null => true
- t.string :salt, :null => false
- end
- end
-
- def self.down
- drop_table :open_id_authentication_associations
- drop_table :open_id_authentication_nonces
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/templates/migration.rb b/trustie2/lib/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/templates/migration.rb
deleted file mode 100644
index d13bbab23..000000000
--- a/trustie2/lib/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/templates/migration.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-class <%= class_name %> < ActiveRecord::Migration
- def self.up
- drop_table :open_id_authentication_settings
- drop_table :open_id_authentication_nonces
-
- create_table :open_id_authentication_nonces, :force => true do |t|
- t.integer :timestamp, :null => false
- t.string :server_url, :null => true
- t.string :salt, :null => false
- end
- end
-
- def self.down
- drop_table :open_id_authentication_nonces
-
- create_table :open_id_authentication_nonces, :force => true do |t|
- t.integer :created
- t.string :nonce
- end
-
- create_table :open_id_authentication_settings, :force => true do |t|
- t.string :setting
- t.binary :value
- end
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/upgrade_open_id_authentication_tables_generator.rb b/trustie2/lib/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/upgrade_open_id_authentication_tables_generator.rb
deleted file mode 100644
index 02fddd7fd..000000000
--- a/trustie2/lib/plugins/open_id_authentication/generators/upgrade_open_id_authentication_tables/upgrade_open_id_authentication_tables_generator.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class UpgradeOpenIdAuthenticationTablesGenerator < Rails::Generator::NamedBase
- def initialize(runtime_args, runtime_options = {})
- super
- end
-
- def manifest
- record do |m|
- m.migration_template 'migration.rb', 'db/migrate'
- end
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/init.rb b/trustie2/lib/plugins/open_id_authentication/init.rb
deleted file mode 100644
index 84ec11fc4..000000000
--- a/trustie2/lib/plugins/open_id_authentication/init.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-if Rails.version < '3'
- config.gem 'rack-openid', :lib => 'rack/openid', :version => '>=0.2.1'
-end
-
-require 'open_id_authentication'
-
-config.middleware.use OpenIdAuthentication
-
-config.after_initialize do
- OpenID::Util.logger = Rails.logger
- ActionController::Base.send :include, OpenIdAuthentication
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication.rb b/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication.rb
deleted file mode 100644
index 48be8ddba..000000000
--- a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication.rb
+++ /dev/null
@@ -1,159 +0,0 @@
-require 'uri'
-require 'openid'
-require 'rack/openid'
-
-module OpenIdAuthentication
- def self.new(app)
- store = OpenIdAuthentication.store
- if store.nil?
- Rails.logger.warn "OpenIdAuthentication.store is nil. Using in-memory store."
- end
-
- ::Rack::OpenID.new(app, OpenIdAuthentication.store)
- end
-
- def self.store
- @@store
- end
-
- def self.store=(*store_option)
- store, *parameters = *([ store_option ].flatten)
-
- @@store = case store
- when :memory
- require 'openid/store/memory'
- OpenID::Store::Memory.new
- when :file
- require 'openid/store/filesystem'
- OpenID::Store::Filesystem.new(Rails.root.join('tmp/openids'))
- when :memcache
- require 'memcache'
- require 'openid/store/memcache'
- OpenID::Store::Memcache.new(MemCache.new(parameters))
- else
- store
- end
- end
-
- self.store = nil
-
- class InvalidOpenId < StandardError
- end
-
- class Result
- ERROR_MESSAGES = {
- :missing => "Sorry, the OpenID server couldn't be found",
- :invalid => "Sorry, but this does not appear to be a valid OpenID",
- :canceled => "OpenID verification was canceled",
- :failed => "OpenID verification failed",
- :setup_needed => "OpenID verification needs setup"
- }
-
- def self.[](code)
- new(code)
- end
-
- def initialize(code)
- @code = code
- end
-
- def status
- @code
- end
-
- ERROR_MESSAGES.keys.each { |state| define_method("#{state}?") { @code == state } }
-
- def successful?
- @code == :successful
- end
-
- def unsuccessful?
- ERROR_MESSAGES.keys.include?(@code)
- end
-
- def message
- ERROR_MESSAGES[@code]
- end
- end
-
- # normalizes an OpenID according to http://openid.net/specs/openid-authentication-2_0.html#normalization
- def self.normalize_identifier(identifier)
- # clean up whitespace
- identifier = identifier.to_s.strip
-
- # if an XRI has a prefix, strip it.
- identifier.gsub!(/xri:\/\//i, '')
-
- # dodge XRIs -- TODO: validate, don't just skip.
- unless ['=', '@', '+', '$', '!', '('].include?(identifier.at(0))
- # does it begin with http? if not, add it.
- identifier = "http://#{identifier}" unless identifier =~ /^http/i
-
- # strip any fragments
- identifier.gsub!(/\#(.*)$/, '')
-
- begin
- uri = URI.parse(identifier)
- uri.scheme = uri.scheme.downcase if uri.scheme # URI should do this
- identifier = uri.normalize.to_s
- rescue URI::InvalidURIError
- raise InvalidOpenId.new("#{identifier} is not an OpenID identifier")
- end
- end
-
- return identifier
- end
-
- protected
- # The parameter name of "openid_identifier" is used rather than
- # the Rails convention "open_id_identifier" because that's what
- # the specification dictates in order to get browser auto-complete
- # working across sites
- def using_open_id?(identifier = nil) #:doc:
- identifier ||= open_id_identifier
- !identifier.blank? || request.env[Rack::OpenID::RESPONSE]
- end
-
- def authenticate_with_open_id(identifier = nil, options = {}, &block) #:doc:
- identifier ||= open_id_identifier
-
- if request.env[Rack::OpenID::RESPONSE]
- complete_open_id_authentication(&block)
- else
- begin_open_id_authentication(identifier, options, &block)
- end
- end
-
- private
- def open_id_identifier
- params[:openid_identifier] || params[:openid_url]
- end
-
- def begin_open_id_authentication(identifier, options = {})
- options[:identifier] = identifier
- value = Rack::OpenID.build_header(options)
- response.headers[Rack::OpenID::AUTHENTICATE_HEADER] = value
- head :unauthorized
- end
-
- def complete_open_id_authentication
- response = request.env[Rack::OpenID::RESPONSE]
- identifier = response.display_identifier
-
- case response.status
- when OpenID::Consumer::SUCCESS
- yield Result[:successful], identifier,
- OpenID::SReg::Response.from_success_response(response)
- when :missing
- yield Result[:missing], identifier, nil
- when :invalid
- yield Result[:invalid], identifier, nil
- when OpenID::Consumer::CANCEL
- yield Result[:canceled], identifier, nil
- when OpenID::Consumer::FAILURE
- yield Result[:failed], identifier, nil
- when OpenID::Consumer::SETUP_NEEDED
- yield Result[:setup_needed], response.setup_url, nil
- end
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/association.rb b/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/association.rb
deleted file mode 100644
index 8ab71bec0..000000000
--- a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/association.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module OpenIdAuthentication
- class Association < ActiveRecord::Base
- self.table_name = :open_id_authentication_associations
-
- def from_record
- OpenID::Association.new(handle, secret, issued, lifetime, assoc_type)
- end
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/db_store.rb b/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/db_store.rb
deleted file mode 100644
index 780fb6ad2..000000000
--- a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/db_store.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-require 'openid/store/interface'
-
-module OpenIdAuthentication
- class DbStore < OpenID::Store::Interface
- def self.cleanup_nonces
- now = Time.now.to_i
- Nonce.delete_all(["timestamp > ? OR timestamp < ?", now + OpenID::Nonce.skew, now - OpenID::Nonce.skew])
- end
-
- def self.cleanup_associations
- now = Time.now.to_i
- Association.delete_all(['issued + lifetime > ?',now])
- end
-
- def store_association(server_url, assoc)
- remove_association(server_url, assoc.handle)
- Association.create(:server_url => server_url,
- :handle => assoc.handle,
- :secret => assoc.secret,
- :issued => assoc.issued,
- :lifetime => assoc.lifetime,
- :assoc_type => assoc.assoc_type)
- end
-
- def get_association(server_url, handle = nil)
- assocs = if handle.blank?
- Association.find_all_by_server_url(server_url)
- else
- Association.find_all_by_server_url_and_handle(server_url, handle)
- end
-
- assocs.reverse.each do |assoc|
- a = assoc.from_record
- if a.expires_in == 0
- assoc.destroy
- else
- return a
- end
- end if assocs.any?
-
- return nil
- end
-
- def remove_association(server_url, handle)
- Association.delete_all(['server_url = ? AND handle = ?', server_url, handle]) > 0
- end
-
- def use_nonce(server_url, timestamp, salt)
- return false if Nonce.find_by_server_url_and_timestamp_and_salt(server_url, timestamp, salt)
- return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
- Nonce.create(:server_url => server_url, :timestamp => timestamp, :salt => salt)
- return true
- end
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/mem_cache_store.rb b/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/mem_cache_store.rb
deleted file mode 100644
index b520e4a8b..000000000
--- a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/mem_cache_store.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require 'digest/sha1'
-require 'openid/store/interface'
-
-module OpenIdAuthentication
- class MemCacheStore < OpenID::Store::Interface
- def initialize(*addresses)
- @connection = ActiveSupport::Cache::MemCacheStore.new(addresses)
- end
-
- def store_association(server_url, assoc)
- server_key = association_server_key(server_url)
- assoc_key = association_key(server_url, assoc.handle)
-
- assocs = @connection.read(server_key) || {}
- assocs[assoc.issued] = assoc_key
-
- @connection.write(server_key, assocs)
- @connection.write(assoc_key, assoc, :expires_in => assoc.lifetime)
- end
-
- def get_association(server_url, handle = nil)
- if handle
- @connection.read(association_key(server_url, handle))
- else
- server_key = association_server_key(server_url)
- assocs = @connection.read(server_key)
- return if assocs.nil?
-
- last_key = assocs[assocs.keys.sort.last]
- @connection.read(last_key)
- end
- end
-
- def remove_association(server_url, handle)
- server_key = association_server_key(server_url)
- assoc_key = association_key(server_url, handle)
- assocs = @connection.read(server_key)
-
- return false unless assocs && assocs.has_value?(assoc_key)
-
- assocs = assocs.delete_if { |key, value| value == assoc_key }
-
- @connection.write(server_key, assocs)
- @connection.delete(assoc_key)
-
- return true
- end
-
- def use_nonce(server_url, timestamp, salt)
- return false if @connection.read(nonce_key(server_url, salt))
- return false if (timestamp - Time.now.to_i).abs > OpenID::Nonce.skew
- @connection.write(nonce_key(server_url, salt), timestamp, :expires_in => OpenID::Nonce.skew)
- return true
- end
-
- private
- def association_key(server_url, handle = nil)
- "openid_association_#{digest(server_url)}_#{digest(handle)}"
- end
-
- def association_server_key(server_url)
- "openid_association_server_#{digest(server_url)}"
- end
-
- def nonce_key(server_url, salt)
- "openid_nonce_#{digest(server_url)}_#{digest(salt)}"
- end
-
- def digest(text)
- Digest::SHA1.hexdigest(text)
- end
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/nonce.rb b/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/nonce.rb
deleted file mode 100644
index b28bf1679..000000000
--- a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/nonce.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module OpenIdAuthentication
- class Nonce < ActiveRecord::Base
- self.table_name = :open_id_authentication_nonces
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/request.rb b/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/request.rb
deleted file mode 100644
index e0cc8e3fc..000000000
--- a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/request.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-module OpenIdAuthentication
- module Request
- def self.included(base)
- base.alias_method_chain :request_method, :openid
- end
-
- def request_method_with_openid
- if !parameters[:_method].blank? && parameters[:open_id_complete] == '1'
- parameters[:_method].to_sym
- else
- request_method_without_openid
- end
- end
- end
-end
-
-# In Rails 2.3, the request object has been renamed
-# from AbstractRequest to Request
-if defined? ActionController::Request
- ActionController::Request.send :include, OpenIdAuthentication::Request
-else
- ActionController::AbstractRequest.send :include, OpenIdAuthentication::Request
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/timeout_fixes.rb b/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/timeout_fixes.rb
deleted file mode 100644
index cc711c9ac..000000000
--- a/trustie2/lib/plugins/open_id_authentication/lib/open_id_authentication/timeout_fixes.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# http://trac.openidenabled.com/trac/ticket/156
-module OpenID
- @@timeout_threshold = 20
-
- def self.timeout_threshold
- @@timeout_threshold
- end
-
- def self.timeout_threshold=(value)
- @@timeout_threshold = value
- end
-
- class StandardFetcher
- def make_http(uri)
- http = @proxy.new(uri.host, uri.port)
- http.read_timeout = http.open_timeout = OpenID.timeout_threshold
- http
- end
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/open_id_authentication/lib/tasks/open_id_authentication_tasks.rake b/trustie2/lib/plugins/open_id_authentication/lib/tasks/open_id_authentication_tasks.rake
deleted file mode 100644
index c71434a50..000000000
--- a/trustie2/lib/plugins/open_id_authentication/lib/tasks/open_id_authentication_tasks.rake
+++ /dev/null
@@ -1,30 +0,0 @@
-namespace :open_id_authentication do
- namespace :db do
- desc "Creates authentication tables for use with OpenIdAuthentication"
- task :create => :environment do
- generate_migration(["open_id_authentication_tables", "add_open_id_authentication_tables"])
- end
-
- desc "Upgrade authentication tables from ruby-openid 1.x.x to 2.x.x"
- task :upgrade => :environment do
- generate_migration(["upgrade_open_id_authentication_tables", "upgrade_open_id_authentication_tables"])
- end
-
- def generate_migration(args)
- require 'rails_generator'
- require 'rails_generator/scripts/generate'
-
- if ActiveRecord::Base.connection.supports_migrations?
- Rails::Generator::Scripts::Generate.new.run(args)
- else
- raise "Task unavailable to this database (no migration support)"
- end
- end
-
- desc "Clear the authentication tables"
- task :clear => :environment do
- OpenIdAuthentication::DbStore.cleanup_nonces
- OpenIdAuthentication::DbStore.cleanup_associations
- end
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/test/mem_cache_store_test.rb b/trustie2/lib/plugins/open_id_authentication/test/mem_cache_store_test.rb
deleted file mode 100644
index 18a943979..000000000
--- a/trustie2/lib/plugins/open_id_authentication/test/mem_cache_store_test.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-require File.dirname(__FILE__) + '/test_helper'
-require File.dirname(__FILE__) + '/../lib/open_id_authentication/mem_cache_store'
-
-# Mock MemCacheStore with MemoryStore for testing
-class OpenIdAuthentication::MemCacheStore < OpenID::Store::Interface
- def initialize(*addresses)
- @connection = ActiveSupport::Cache::MemoryStore.new
- end
-end
-
-class MemCacheStoreTest < Test::Unit::TestCase
- ALLOWED_HANDLE = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
-
- def setup
- @store = OpenIdAuthentication::MemCacheStore.new
- end
-
- def test_store
- server_url = "http://www.myopenid.com/openid"
- assoc = gen_assoc(0)
-
- # Make sure that a missing association returns no result
- assert_retrieve(server_url)
-
- # Check that after storage, getting returns the same result
- @store.store_association(server_url, assoc)
- assert_retrieve(server_url, nil, assoc)
-
- # more than once
- assert_retrieve(server_url, nil, assoc)
-
- # Storing more than once has no ill effect
- @store.store_association(server_url, assoc)
- assert_retrieve(server_url, nil, assoc)
-
- # Removing an association that does not exist returns not present
- assert_remove(server_url, assoc.handle + 'x', false)
-
- # Removing an association that does not exist returns not present
- assert_remove(server_url + 'x', assoc.handle, false)
-
- # Removing an association that is present returns present
- assert_remove(server_url, assoc.handle, true)
-
- # but not present on subsequent calls
- assert_remove(server_url, assoc.handle, false)
-
- # Put assoc back in the store
- @store.store_association(server_url, assoc)
-
- # More recent and expires after assoc
- assoc2 = gen_assoc(1)
- @store.store_association(server_url, assoc2)
-
- # After storing an association with a different handle, but the
- # same server_url, the handle with the later expiration is returned.
- assert_retrieve(server_url, nil, assoc2)
-
- # We can still retrieve the older association
- assert_retrieve(server_url, assoc.handle, assoc)
-
- # Plus we can retrieve the association with the later expiration
- # explicitly
- assert_retrieve(server_url, assoc2.handle, assoc2)
-
- # More recent, and expires earlier than assoc2 or assoc. Make sure
- # that we're picking the one with the latest issued date and not
- # taking into account the expiration.
- assoc3 = gen_assoc(2, 100)
- @store.store_association(server_url, assoc3)
-
- assert_retrieve(server_url, nil, assoc3)
- assert_retrieve(server_url, assoc.handle, assoc)
- assert_retrieve(server_url, assoc2.handle, assoc2)
- assert_retrieve(server_url, assoc3.handle, assoc3)
-
- assert_remove(server_url, assoc2.handle, true)
-
- assert_retrieve(server_url, nil, assoc3)
- assert_retrieve(server_url, assoc.handle, assoc)
- assert_retrieve(server_url, assoc2.handle, nil)
- assert_retrieve(server_url, assoc3.handle, assoc3)
-
- assert_remove(server_url, assoc2.handle, false)
- assert_remove(server_url, assoc3.handle, true)
-
- assert_retrieve(server_url, nil, assoc)
- assert_retrieve(server_url, assoc.handle, assoc)
- assert_retrieve(server_url, assoc2.handle, nil)
- assert_retrieve(server_url, assoc3.handle, nil)
-
- assert_remove(server_url, assoc2.handle, false)
- assert_remove(server_url, assoc.handle, true)
- assert_remove(server_url, assoc3.handle, false)
-
- assert_retrieve(server_url, nil, nil)
- assert_retrieve(server_url, assoc.handle, nil)
- assert_retrieve(server_url, assoc2.handle, nil)
- assert_retrieve(server_url, assoc3.handle, nil)
-
- assert_remove(server_url, assoc2.handle, false)
- assert_remove(server_url, assoc.handle, false)
- assert_remove(server_url, assoc3.handle, false)
- end
-
- def test_nonce
- server_url = "http://www.myopenid.com/openid"
-
- [server_url, ''].each do |url|
- nonce1 = OpenID::Nonce::mk_nonce
-
- assert_nonce(nonce1, true, url, "#{url}: nonce allowed by default")
- assert_nonce(nonce1, false, url, "#{url}: nonce not allowed twice")
- assert_nonce(nonce1, false, url, "#{url}: nonce not allowed third time")
-
- # old nonces shouldn't pass
- old_nonce = OpenID::Nonce::mk_nonce(3600)
- assert_nonce(old_nonce, false, url, "Old nonce #{old_nonce.inspect} passed")
- end
- end
-
- private
- def gen_assoc(issued, lifetime = 600)
- secret = OpenID::CryptUtil.random_string(20, nil)
- handle = OpenID::CryptUtil.random_string(128, ALLOWED_HANDLE)
- OpenID::Association.new(handle, secret, Time.now + issued, lifetime, 'HMAC-SHA1')
- end
-
- def assert_retrieve(url, handle = nil, expected = nil)
- assoc = @store.get_association(url, handle)
-
- if expected.nil?
- assert_nil(assoc)
- else
- assert_equal(expected, assoc)
- assert_equal(expected.handle, assoc.handle)
- assert_equal(expected.secret, assoc.secret)
- end
- end
-
- def assert_remove(url, handle, expected)
- present = @store.remove_association(url, handle)
- assert_equal(expected, present)
- end
-
- def assert_nonce(nonce, expected, server_url, msg = "")
- stamp, salt = OpenID::Nonce::split_nonce(nonce)
- actual = @store.use_nonce(server_url, stamp, salt)
- assert_equal(expected, actual, msg)
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/test/normalize_test.rb b/trustie2/lib/plugins/open_id_authentication/test/normalize_test.rb
deleted file mode 100644
index 635d3abc9..000000000
--- a/trustie2/lib/plugins/open_id_authentication/test/normalize_test.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require File.dirname(__FILE__) + '/test_helper'
-
-class NormalizeTest < Test::Unit::TestCase
- include OpenIdAuthentication
-
- NORMALIZATIONS = {
- "openid.aol.com/nextangler" => "http://openid.aol.com/nextangler",
- "http://openid.aol.com/nextangler" => "http://openid.aol.com/nextangler",
- "https://openid.aol.com/nextangler" => "https://openid.aol.com/nextangler",
- "HTTP://OPENID.AOL.COM/NEXTANGLER" => "http://openid.aol.com/NEXTANGLER",
- "HTTPS://OPENID.AOL.COM/NEXTANGLER" => "https://openid.aol.com/NEXTANGLER",
- "loudthinking.com" => "http://loudthinking.com/",
- "http://loudthinking.com" => "http://loudthinking.com/",
- "http://loudthinking.com:80" => "http://loudthinking.com/",
- "https://loudthinking.com:443" => "https://loudthinking.com/",
- "http://loudthinking.com:8080" => "http://loudthinking.com:8080/",
- "techno-weenie.net" => "http://techno-weenie.net/",
- "http://techno-weenie.net" => "http://techno-weenie.net/",
- "http://techno-weenie.net " => "http://techno-weenie.net/",
- "=name" => "=name"
- }
-
- def test_normalizations
- NORMALIZATIONS.each do |from, to|
- assert_equal to, normalize_identifier(from)
- end
- end
-
- def test_broken_open_id
- assert_raises(InvalidOpenId) { normalize_identifier(nil) }
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/test/open_id_authentication_test.rb b/trustie2/lib/plugins/open_id_authentication/test/open_id_authentication_test.rb
deleted file mode 100644
index ddcc17b96..000000000
--- a/trustie2/lib/plugins/open_id_authentication/test/open_id_authentication_test.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require File.dirname(__FILE__) + '/test_helper'
-
-class OpenIdAuthenticationTest < Test::Unit::TestCase
- def setup
- @controller = Class.new do
- include OpenIdAuthentication
- def params() {} end
- end.new
- end
-
- def test_authentication_should_fail_when_the_identity_server_is_missing
- open_id_consumer = mock()
- open_id_consumer.expects(:begin).raises(OpenID::OpenIDError)
- @controller.expects(:open_id_consumer).returns(open_id_consumer)
- @controller.expects(:logger).returns(mock(:error => true))
-
- @controller.send(:authenticate_with_open_id, "http://someone.example.com") do |result, identity_url|
- assert result.missing?
- assert_equal "Sorry, the OpenID server couldn't be found", result.message
- end
- end
-
- def test_authentication_should_be_invalid_when_the_identity_url_is_invalid
- @controller.send(:authenticate_with_open_id, "!") do |result, identity_url|
- assert result.invalid?, "Result expected to be invalid but was not"
- assert_equal "Sorry, but this does not appear to be a valid OpenID", result.message
- end
- end
-
- def test_authentication_should_fail_when_the_identity_server_times_out
- open_id_consumer = mock()
- open_id_consumer.expects(:begin).raises(Timeout::Error, "Identity Server took too long.")
- @controller.expects(:open_id_consumer).returns(open_id_consumer)
- @controller.expects(:logger).returns(mock(:error => true))
-
- @controller.send(:authenticate_with_open_id, "http://someone.example.com") do |result, identity_url|
- assert result.missing?
- assert_equal "Sorry, the OpenID server couldn't be found", result.message
- end
- end
-
- def test_authentication_should_begin_when_the_identity_server_is_present
- @controller.expects(:begin_open_id_authentication)
- @controller.send(:authenticate_with_open_id, "http://someone.example.com")
- end
-end
diff --git a/trustie2/lib/plugins/open_id_authentication/test/status_test.rb b/trustie2/lib/plugins/open_id_authentication/test/status_test.rb
deleted file mode 100644
index b1d5e0933..000000000
--- a/trustie2/lib/plugins/open_id_authentication/test/status_test.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require File.dirname(__FILE__) + '/test_helper'
-
-class StatusTest < Test::Unit::TestCase
- include OpenIdAuthentication
-
- def test_state_conditional
- assert Result[:missing].missing?
- assert Result[:missing].unsuccessful?
- assert !Result[:missing].successful?
-
- assert Result[:successful].successful?
- assert !Result[:successful].unsuccessful?
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/plugins/open_id_authentication/test/test_helper.rb b/trustie2/lib/plugins/open_id_authentication/test/test_helper.rb
deleted file mode 100644
index 43216e1ef..000000000
--- a/trustie2/lib/plugins/open_id_authentication/test/test_helper.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'test/unit'
-require 'rubygems'
-
-gem 'activesupport'
-require 'active_support'
-
-gem 'actionpack'
-require 'action_controller'
-
-gem 'mocha'
-require 'mocha'
-
-gem 'ruby-openid'
-require 'openid'
-
-RAILS_ROOT = File.dirname(__FILE__) unless defined? RAILS_ROOT
-require File.dirname(__FILE__) + "/../lib/open_id_authentication"
diff --git a/trustie2/lib/redcloth3.rb b/trustie2/lib/redcloth3.rb
deleted file mode 100644
index b0bda81a5..000000000
--- a/trustie2/lib/redcloth3.rb
+++ /dev/null
@@ -1,1208 +0,0 @@
-# vim:ts=4:sw=4:
-# = RedCloth - Textile and Markdown Hybrid for Ruby
-#
-# Homepage:: http://whytheluckystiff.net/ruby/redcloth/
-# Author:: why the lucky stiff (http://whytheluckystiff.net/)
-# Copyright:: (cc) 2004 why the lucky stiff (and his puppet organizations.)
-# License:: BSD
-#
-# (see http://hobix.com/textile/ for a Textile Reference.)
-#
-# Based on (and also inspired by) both:
-#
-# PyTextile: http://diveintomark.org/projects/textile/textile.py.txt
-# Textism for PHP: http://www.textism.com/tools/textile/
-#
-#
-
-# = RedCloth
-#
-# RedCloth is a Ruby library for converting Textile and/or Markdown
-# into HTML. You can use either format, intermingled or separately.
-# You can also extend RedCloth to honor your own custom text stylings.
-#
-# RedCloth users are encouraged to use Textile if they are generating
-# HTML and to use Markdown if others will be viewing the plain text.
-#
-# == What is Textile?
-#
-# Textile is a simple formatting style for text
-# documents, loosely based on some HTML conventions.
-#
-# == Sample Textile Text
-#
-# h3. This is a title
-#
-# h3. This is a subhead
-#
-# This is a bit of paragraph.
-#
-# bq. This is a blockquote.
-#
-# = Writing Textile
-#
-# A Textile document consists of paragraphs. Paragraphs
-# can be specially formatted by adding a small instruction
-# to the beginning of the paragraph.
-#
-# h[n]. Header of size [n].
-# bq. Blockquote.
-# # Numeric list.
-# * Bulleted list.
-#
-# == Quick Phrase Modifiers
-#
-# Quick phrase modifiers are also included, to allow formatting
-# of small portions of text within a paragraph.
-#
-# \_emphasis\_
-# \_\_italicized\_\_
-# \*strong\*
-# \*\*bold\*\*
-# ??citation??
-# -deleted text-
-# +inserted text+
-# ^superscript^
-# ~subscript~
-# @code@
-# %(classname)span%
-#
-# ==notextile== (leave text alone)
-#
-# == Links
-#
-# To make a hypertext link, put the link text in "quotation
-# marks" followed immediately by a colon and the URL of the link.
-#
-# Optional: text in (parentheses) following the link text,
-# but before the closing quotation mark, will become a Title
-# attribute for the link, visible as a tool tip when a cursor is above it.
-#
-# Example:
-#
-# "This is a link (This is a title) ":http://www.textism.com
-#
-# Will become:
-#
-# This is a link
-#
-# == Images
-#
-# To insert an image, put the URL for the image inside exclamation marks.
-#
-# Optional: text that immediately follows the URL in (parentheses) will
-# be used as the Alt text for the image. Images on the web should always
-# have descriptive Alt text for the benefit of readers using non-graphical
-# browsers.
-#
-# Optional: place a colon followed by a URL immediately after the
-# closing ! to make the image into a link.
-#
-# Example:
-#
-# !http://www.textism.com/common/textist.gif(Textist)!
-#
-# Will become:
-#
-#
-#
-# With a link:
-#
-# !/common/textist.gif(Textist)!:http://textism.com
-#
-# Will become:
-#
-#
-#
-# == Defining Acronyms
-#
-# HTML allows authors to define acronyms via the tag. The definition appears as a
-# tool tip when a cursor hovers over the acronym. A crucial aid to clear writing,
-# this should be used at least once for each acronym in documents where they appear.
-#
-# To quickly define an acronym in Textile, place the full text in (parentheses)
-# immediately following the acronym.
-#
-# Example:
-#
-# ACLU(American Civil Liberties Union)
-#
-# Will become:
-#
-# ACLU
-#
-# == Adding Tables
-#
-# In Textile, simple tables can be added by seperating each column by
-# a pipe.
-#
-# |a|simple|table|row|
-# |And|Another|table|row|
-#
-# Attributes are defined by style definitions in parentheses.
-#
-# table(border:1px solid black).
-# (background:#ddd;color:red). |{}| | | |
-#
-# == Using RedCloth
-#
-# RedCloth is simply an extension of the String class, which can handle
-# Textile formatting. Use it like a String and output HTML with its
-# RedCloth#to_html method.
-#
-# doc = RedCloth.new "
-#
-# h3. Test document
-#
-# Just a simple test."
-#
-# puts doc.to_html
-#
-# By default, RedCloth uses both Textile and Markdown formatting, with
-# Textile formatting taking precedence. If you want to turn off Markdown
-# formatting, to boost speed and limit the processor:
-#
-# class RedCloth::Textile.new( str )
-
-class RedCloth3 < String
-
- VERSION = '3.0.4'
- DEFAULT_RULES = [:textile, :markdown]
-
- #
- # Two accessor for setting security restrictions.
- #
- # This is a nice thing if you're using RedCloth for
- # formatting in public places (e.g. Wikis) where you
- # don't want users to abuse HTML for bad things.
- #
- # If +:filter_html+ is set, HTML which wasn't
- # created by the Textile processor will be escaped.
- #
- # If +:filter_styles+ is set, it will also disable
- # the style markup specifier. ('{color: red}')
- #
- attr_accessor :filter_html, :filter_styles
-
- #
- # Accessor for toggling hard breaks.
- #
- # If +:hard_breaks+ is set, single newlines will
- # be converted to HTML break tags. This is the
- # default behavior for traditional RedCloth.
- #
- attr_accessor :hard_breaks
-
- # Accessor for toggling lite mode.
- #
- # In lite mode, block-level rules are ignored. This means
- # that tables, paragraphs, lists, and such aren't available.
- # Only the inline markup for bold, italics, entities and so on.
- #
- # r = RedCloth.new( "And then? She *fell*!", [:lite_mode] )
- # r.to_html
- # #=> "And then? She fell!"
- #
- attr_accessor :lite_mode
-
- #
- # Accessor for toggling span caps.
- #
- # Textile places `span' tags around capitalized
- # words by default, but this wreaks havoc on Wikis.
- # If +:no_span_caps+ is set, this will be
- # suppressed.
- #
- attr_accessor :no_span_caps
-
- #
- # Establishes the markup predence. Available rules include:
- #
- # == Textile Rules
- #
- # The following textile rules can be set individually. Or add the complete
- # set of rules with the single :textile rule, which supplies the rule set in
- # the following precedence:
- #
- # refs_textile:: Textile references (i.e. [hobix]http://hobix.com/)
- # block_textile_table:: Textile table block structures
- # block_textile_lists:: Textile list structures
- # block_textile_prefix:: Textile blocks with prefixes (i.e. bq., h3., etc.)
- # inline_textile_image:: Textile inline images
- # inline_textile_link:: Textile inline links
- # inline_textile_span:: Textile inline spans
- # glyphs_textile:: Textile entities (such as em-dashes and smart quotes)
- #
- # == Markdown
- #
- # refs_markdown:: Markdown references (for example: [hobix]: http://hobix.com/)
- # block_markdown_setext:: Markdown setext headers
- # block_markdown_atx:: Markdown atx headers
- # block_markdown_rule:: Markdown horizontal rules
- # block_markdown_bq:: Markdown blockquotes
- # block_markdown_lists:: Markdown lists
- # inline_markdown_link:: Markdown links
- attr_accessor :rules
-
- # Returns a new RedCloth object, based on _string_ and
- # enforcing all the included _restrictions_.
- #
- # r = RedCloth.new( "h1. A bold man", [:filter_html] )
- # r.to_html
- # #=>"A <b>bold</b> man
"
- #
- def initialize( string, restrictions = [] )
- restrictions.each { |r| method( "#{ r }=" ).call( true ) }
- super( string )
- end
-
- #
- # Generates HTML from the Textile contents.
- #
- # r = RedCloth.new( "And then? She *fell*!" )
- # r.to_html( true )
- # #=>"And then? She fell!"
- #
- def to_html( *rules )
- rules = DEFAULT_RULES if rules.empty?
- # make our working copy
- text = self.dup
-
- @urlrefs = {}
- @shelf = []
- textile_rules = [:block_textile_table, :block_textile_lists,
- :block_textile_prefix, :inline_textile_image, :inline_textile_link,
- :inline_textile_code, :inline_textile_span, :glyphs_textile]
- markdown_rules = [:refs_markdown, :block_markdown_setext, :block_markdown_atx, :block_markdown_rule,
- :block_markdown_bq, :block_markdown_lists,
- :inline_markdown_reflink, :inline_markdown_link]
- @rules = rules.collect do |rule|
- case rule
- when :markdown
- markdown_rules
- when :textile
- textile_rules
- else
- rule
- end
- end.flatten
-
- # standard clean up
- incoming_entities text
- clean_white_space text
-
- # start processor
- @pre_list = []
- rip_offtags text
- no_textile text
- escape_html_tags text
- # need to do this before #hard_break and #blocks
- block_textile_quotes text unless @lite_mode
- hard_break text
- unless @lite_mode
- refs text
- blocks text
- end
- inline text
- smooth_offtags text
-
- retrieve text
-
- text.gsub!( /<\/?notextile>/, '' )
- text.gsub!( /x%x%/, '&' )
- clean_html text if filter_html
- text.strip!
- text
-
- end
-
- #######
- private
- #######
- #
- # Mapping of 8-bit ASCII codes to HTML numerical entity equivalents.
- # (from PyTextile)
- #
- TEXTILE_TAGS =
-
- [[128, 8364], [129, 0], [130, 8218], [131, 402], [132, 8222], [133, 8230],
- [134, 8224], [135, 8225], [136, 710], [137, 8240], [138, 352], [139, 8249],
- [140, 338], [141, 0], [142, 0], [143, 0], [144, 0], [145, 8216], [146, 8217],
- [147, 8220], [148, 8221], [149, 8226], [150, 8211], [151, 8212], [152, 732],
- [153, 8482], [154, 353], [155, 8250], [156, 339], [157, 0], [158, 0], [159, 376]].
-
- collect! do |a, b|
- [a.chr, ( b.zero? and "" or "{ b };" )]
- end
-
- #
- # Regular expressions to convert to HTML.
- #
- A_HLGN = /(?:(?:<>|<|>|\=|[()]+)+)/
- A_VLGN = /[\-^~]/
- C_CLAS = '(?:\([^")]+\))'
- C_LNGE = '(?:\[[^"\[\]]+\])'
- C_STYL = '(?:\{[^"}]+\})'
- S_CSPN = '(?:\\\\\d+)'
- S_RSPN = '(?:/\d+)'
- A = "(?:#{A_HLGN}?#{A_VLGN}?|#{A_VLGN}?#{A_HLGN}?)"
- S = "(?:#{S_CSPN}?#{S_RSPN}|#{S_RSPN}?#{S_CSPN}?)"
- C = "(?:#{C_CLAS}?#{C_STYL}?#{C_LNGE}?|#{C_STYL}?#{C_LNGE}?#{C_CLAS}?|#{C_LNGE}?#{C_STYL}?#{C_CLAS}?)"
- # PUNCT = Regexp::quote( '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' )
- PUNCT = Regexp::quote( '!"#$%&\'*+,-./:;=?@\\^_`|~' )
- PUNCT_NOQ = Regexp::quote( '!"#$&\',./:;=?@\\`|' )
- PUNCT_Q = Regexp::quote( '*-_+^~%' )
- HYPERLINK = '(\S+?)([^\w\s/;=\?]*?)(?=\s|<|$)'
-
- # Text markup tags, don't conflict with block tags
- SIMPLE_HTML_TAGS = [
- 'tt', 'b', 'i', 'big', 'small', 'em', 'strong', 'dfn', 'code',
- 'samp', 'kbd', 'var', 'cite', 'abbr', 'acronym', 'a', 'img', 'br',
- 'br', 'map', 'q', 'sub', 'sup', 'span', 'bdo'
- ]
-
- QTAGS = [
- ['**', 'b', :limit],
- ['*', 'strong', :limit],
- ['??', 'cite', :limit],
- ['-', 'del', :limit],
- ['__', 'i', :limit],
- ['_', 'em', :limit],
- ['%', 'span', :limit],
- ['+', 'ins', :limit],
- ['^', 'sup', :limit],
- ['~', 'sub', :limit]
- ]
- QTAGS_JOIN = QTAGS.map {|rc, ht, rtype| Regexp::quote rc}.join('|')
-
- QTAGS.collect! do |rc, ht, rtype|
- rcq = Regexp::quote rc
- re =
- case rtype
- when :limit
- /(^|[>\s\(]) # sta
- (?!\-\-)
- (#{QTAGS_JOIN}|) # oqs
- (#{rcq}) # qtag
- (\w|[^\s].*?[^\s]) # content
- (?!\-\-)
- #{rcq}
- (#{QTAGS_JOIN}|) # oqa
- (?=[[:punct:]]|<|\s|\)|$)/x
- else
- /(#{rcq})
- (#{C})
- (?::(\S+))?
- (\w|[^\s\-].*?[^\s\-])
- #{rcq}/xm
- end
- [rc, ht, re, rtype]
- end
-
- # Elements to handle
- GLYPHS = [
- # [ /([^\s\[{(>])?\'([dmst]\b|ll\b|ve\b|\s|:|$)/, '\1’\2' ], # single closing
- # [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)\'/, '\1’' ], # single closing
- # [ /\'(?=[#{PUNCT_Q}]*(s\b|[\s#{PUNCT_NOQ}]))/, '’' ], # single closing
- # [ /\'/, '‘' ], # single opening
- # [ /, '<' ], # less-than
- # [ />/, '>' ], # greater-than
- # [ /([^\s\[{(])?"(\s|:|$)/, '\1”\2' ], # double closing
- # [ /([^\s\[{(>#{PUNCT_Q}][#{PUNCT_Q}]*)"/, '\1”' ], # double closing
- # [ /"(?=[#{PUNCT_Q}]*[\s#{PUNCT_NOQ}])/, '”' ], # double closing
- # [ /"/, '“' ], # double opening
- # [ /\b( )?\.{3}/, '\1…' ], # ellipsis
- # [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '\1' ], # 3+ uppercase acronym
- # [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]+[A-Z0-9])([^\2\3', :no_span_caps ], # 3+ uppercase caps
- # [ /(\.\s)?\s?--\s?/, '\1—' ], # em dash
- # [ /\s->\s/, ' → ' ], # right arrow
- # [ /\s-\s/, ' – ' ], # en dash
- # [ /(\d+) ?x ?(\d+)/, '\1×\2' ], # dimension sign
- # [ /\b ?[(\[]TM[\])]/i, '™' ], # trademark
- # [ /\b ?[(\[]R[\])]/i, '®' ], # registered
- # [ /\b ?[(\[]C[\])]/i, '©' ] # copyright
- ]
-
- H_ALGN_VALS = {
- '<' => 'left',
- '=' => 'center',
- '>' => 'right',
- '<>' => 'justify'
- }
-
- V_ALGN_VALS = {
- '^' => 'top',
- '-' => 'middle',
- '~' => 'bottom'
- }
-
- #
- # Flexible HTML escaping
- #
- def htmlesc( str, mode=:Quotes )
- if str
- str.gsub!( '&', '&' )
- str.gsub!( '"', '"' ) if mode != :NoQuotes
- str.gsub!( "'", ''' ) if mode == :Quotes
- str.gsub!( '<', '<')
- str.gsub!( '>', '>')
- end
- str
- end
-
- # Search and replace for Textile glyphs (quotes, dashes, other symbols)
- def pgl( text )
- #GLYPHS.each do |re, resub, tog|
- # next if tog and method( tog ).call
- # text.gsub! re, resub
- #end
- text.gsub!(/\b([A-Z][A-Z0-9]{1,})\b(?:[(]([^)]*)[)])/) do |m|
- "#{$1}"
- end
- end
-
- # Parses Textile attribute lists and builds an HTML attribute string
- def pba( text_in, element = "" )
-
- return '' unless text_in
-
- style = []
- text = text_in.dup
- if element == 'td'
- colspan = $1 if text =~ /\\(\d+)/
- rowspan = $1 if text =~ /\/(\d+)/
- style << "vertical-align:#{ v_align( $& ) };" if text =~ A_VLGN
- end
-
- if text.sub!( /\{([^"}]*)\}/, '' ) && !filter_styles
- sanitized = sanitize_styles($1)
- style << "#{ sanitized };" unless sanitized.blank?
- end
-
- lang = $1 if
- text.sub!( /\[([^)]+?)\]/, '' )
-
- cls = $1 if
- text.sub!( /\(([^()]+?)\)/, '' )
-
- style << "padding-left:#{ $1.length }em;" if
- text.sub!( /([(]+)/, '' )
-
- style << "padding-right:#{ $1.length }em;" if text.sub!( /([)]+)/, '' )
-
- style << "text-align:#{ h_align( $& ) };" if text =~ A_HLGN
-
- cls, id = $1, $2 if cls =~ /^(.*?)#(.*)$/
-
- atts = ''
- atts << " style=\"#{ style.join }\"" unless style.empty?
- atts << " class=\"#{ cls }\"" unless cls.to_s.empty?
- atts << " lang=\"#{ lang }\"" if lang
- atts << " id=\"#{ id }\"" if id
- atts << " colspan=\"#{ colspan }\"" if colspan
- atts << " rowspan=\"#{ rowspan }\"" if rowspan
-
- atts
- end
-
- STYLES_RE = /^(color|width|height|border|background|padding|margin|font|text|float)(-[a-z]+)*:\s*((\d+%?|\d+px|\d+(\.\d+)?em|#[0-9a-f]+|[a-z]+)\s*)+$/i
-
- def sanitize_styles(str)
- styles = str.split(";").map(&:strip)
- styles.reject! do |style|
- !style.match(STYLES_RE)
- end
- styles.join(";")
- end
-
- TABLE_RE = /^(?:table(_?#{S}#{A}#{C})\. ?\n)?^(#{A}#{C}\.? ?\|.*?\|)(\n\n|\Z)/m
-
- # Parses a Textile table block, building HTML from the result.
- def block_textile_table( text )
- text.gsub!( TABLE_RE ) do |matches|
-
- tatts, fullrow = $~[1..2]
- tatts = pba( tatts, 'table' )
- tatts = shelve( tatts ) if tatts
- rows = []
-
- fullrow.each_line do |row|
- ratts, row = pba( $1, 'tr' ), $2 if row =~ /^(#{A}#{C}\. )(.*)/m
- cells = []
- row.split( /(\|)(?![^\[\|]*\]\])/ )[1..-2].each do |cell|
- next if cell == '|'
- ctyp = 'd'
- ctyp = 'h' if cell =~ /^_/
-
- catts = ''
- catts, cell = pba( $1, 'td' ), $2 if cell =~ /^(_?#{S}#{A}#{C}\. ?)(.*)/
-
- catts = shelve( catts ) if catts
- cells << "\t\t\t#{ cell } "
- end
- ratts = shelve( ratts ) if ratts
- rows << "\t\t\n#{ cells.join( "\n" ) }\n\t\t "
- end
- "\t\n#{ rows.join( "\n" ) }\n\t
\n\n"
- end
- end
-
- LISTS_RE = /^([#*]+?#{C} .*?)$(?![^#*])/m
- LISTS_CONTENT_RE = /^([#*]+)(#{A}#{C}) (.*)$/m
-
- # Parses Textile lists and generates HTML
- def block_textile_lists( text )
- text.gsub!( LISTS_RE ) do |match|
- lines = match.split( /\n/ )
- last_line = -1
- depth = []
- lines.each_with_index do |line, line_id|
- if line =~ LISTS_CONTENT_RE
- tl,atts,content = $~[1..3]
- if depth.last
- if depth.last.length > tl.length
- (depth.length - 1).downto(0) do |i|
- break if depth[i].length == tl.length
- lines[line_id - 1] << "\n\t#{ lT( depth[i] ) }l>\n\t"
- depth.pop
- end
- end
- if depth.last and depth.last.length == tl.length
- lines[line_id - 1] << ''
- end
- end
- unless depth.last == tl
- depth << tl
- atts = pba( atts )
- atts = shelve( atts ) if atts
- lines[line_id] = "\t<#{ lT(tl) }l#{ atts }>\n\t#{ content }"
- else
- lines[line_id] = "\t\t #{ content }"
- end
- last_line = line_id
-
- else
- last_line = line_id
- end
- if line_id - last_line > 1 or line_id == lines.length - 1
- while v = depth.pop
- lines[last_line] << " \n\t#{ lT( v ) }l>"
- end
- end
- end
- lines.join( "\n" )
- end
- end
-
- QUOTES_RE = /(^>+([^\n]*?)(\n|$))+/m
- QUOTES_CONTENT_RE = /^([> ]+)(.*)$/m
-
- def block_textile_quotes( text )
- text.gsub!( QUOTES_RE ) do |match|
- lines = match.split( /\n/ )
- quotes = ''
- indent = 0
- lines.each do |line|
- line =~ QUOTES_CONTENT_RE
- bq,content = $1, $2
- l = bq.count('>')
- if l != indent
- quotes << ("\n\n" + (l>indent ? '' * (l-indent) : '
' * (indent-l)) + "\n\n")
- indent = l
- end
- quotes << (content + "\n")
- end
- quotes << ("\n" + '' * indent + "\n\n")
- quotes
- end
- end
-
- CODE_RE = /(\W)
- @
- (?:\|(\w+?)\|)?
- (.+?)
- @
- (?=\W)/x
-
- def inline_textile_code( text )
- text.gsub!( CODE_RE ) do |m|
- before,lang,code,after = $~[1..4]
- lang = " lang=\"#{ lang }\"" if lang
- rip_offtags( "#{ before }#{ code }#{ after }", false )
- end
- end
-
- def lT( text )
- text =~ /\#$/ ? 'o' : 'u'
- end
-
- def hard_break( text )
- text.gsub!( /(.)\n(?!\Z| *([#*=]+(\s|$)|[{|]))/, "\\1
" ) if hard_breaks
- end
-
- BLOCKS_GROUP_RE = /\n{2,}(?! )/m
-
- def blocks( text, deep_code = false )
- text.replace( text.split( BLOCKS_GROUP_RE ).collect do |blk|
- plain = blk !~ /\A[#*> ]/
-
- # skip blocks that are complex HTML
- if blk =~ /^<\/?(\w+).*>/ and not SIMPLE_HTML_TAGS.include? $1
- blk
- else
- # search for indentation levels
- blk.strip!
- if blk.empty?
- blk
- else
- code_blk = nil
- blk.gsub!( /((?:\n(?:\n^ +[^\n]*)+)+)/m ) do |iblk|
- flush_left iblk
- blocks iblk, plain
- iblk.gsub( /^(\S)/, "\t\\1" )
- if plain
- code_blk = iblk; ""
- else
- iblk
- end
- end
-
- block_applied = 0
- @rules.each do |rule_name|
- block_applied += 1 if ( rule_name.to_s.match /^block_/ and method( rule_name ).call( blk ) )
- end
- if block_applied.zero?
- if deep_code
- blk = "\t#{ blk }
"
- else
- blk = "\t#{ blk }
"
- end
- end
- # hard_break blk
- blk + "\n#{ code_blk }"
- end
- end
-
- end.join( "\n\n" ) )
- end
-
- def textile_bq( tag, atts, cite, content )
- cite, cite_title = check_refs( cite )
- cite = " cite=\"#{ cite }\"" if cite
- atts = shelve( atts ) if atts
- "\t\n\t\t#{ content }
\n\t
"
- end
-
- def textile_p( tag, atts, cite, content )
- atts = shelve( atts ) if atts
- "\t<#{ tag }#{ atts }>#{ content }#{ tag }>"
- end
-
- alias textile_h1 textile_p
- alias textile_h3 textile_p
- alias textile_h3 textile_p
- alias textile_h4 textile_p
- alias textile_h5 textile_p
- alias textile_h6 textile_p
-
- def textile_fn_( tag, num, atts, cite, content )
- atts << " id=\"fn#{ num }\" class=\"footnote\""
- content = "#{ num } #{ content }"
- atts = shelve( atts ) if atts
- "\t#{ content }
"
- end
-
- BLOCK_RE = /^(([a-z]+)(\d*))(#{A}#{C})\.(?::(\S+))? (.*)$/m
-
- def block_textile_prefix( text )
- if text =~ BLOCK_RE
- tag,tagpre,num,atts,cite,content = $~[1..6]
- atts = pba( atts )
-
- # pass to prefix handler
- replacement = nil
- if respond_to? "textile_#{ tag }", true
- replacement = method( "textile_#{ tag }" ).call( tag, atts, cite, content )
- elsif respond_to? "textile_#{ tagpre }_", true
- replacement = method( "textile_#{ tagpre }_" ).call( tagpre, num, atts, cite, content )
- end
- text.gsub!( $& ) { replacement } if replacement
- end
- end
-
- SETEXT_RE = /\A(.+?)\n([=-])[=-]* *$/m
- def block_markdown_setext( text )
- if text =~ SETEXT_RE
- tag = if $2 == "="; "h1"; else; "h3"; end
- blk, cont = "<#{ tag }>#{ $1 }#{ tag }>", $'
- blocks cont
- text.replace( blk + cont )
- end
- end
-
- ATX_RE = /\A(\#{1,6}) # $1 = string of #'s
- [ ]*
- (.+?) # $2 = Header text
- [ ]*
- \#* # optional closing #'s (not counted)
- $/x
- def block_markdown_atx( text )
- if text =~ ATX_RE
- tag = "h#{ $1.length }"
- blk, cont = "<#{ tag }>#{ $2 }#{ tag }>\n\n", $'
- blocks cont
- text.replace( blk + cont )
- end
- end
-
- MARKDOWN_BQ_RE = /\A(^ *> ?.+$(.+\n)*\n*)+/m
-
- def block_markdown_bq( text )
- text.gsub!( MARKDOWN_BQ_RE ) do |blk|
- blk.gsub!( /^ *> ?/, '' )
- flush_left blk
- blocks blk
- blk.gsub!( /^(\S)/, "\t\\1" )
- "\n#{ blk }\n
\n\n"
- end
- end
-
- MARKDOWN_RULE_RE = /^(#{
- ['*', '-', '_'].collect { |ch| ' ?(' + Regexp::quote( ch ) + ' ?){3,}' }.join( '|' )
- })$/
-
- def block_markdown_rule( text )
- text.gsub!( MARKDOWN_RULE_RE ) do |blk|
- "
"
- end
- end
-
- # XXX TODO XXX
- def block_markdown_lists( text )
- end
-
- def inline_textile_span( text )
- QTAGS.each do |qtag_rc, ht, qtag_re, rtype|
- text.gsub!( qtag_re ) do |m|
-
- case rtype
- when :limit
- sta,oqs,qtag,content,oqa = $~[1..6]
- atts = nil
- if content =~ /^(#{C})(.+)$/
- atts, content = $~[1..2]
- end
- else
- qtag,atts,cite,content = $~[1..4]
- sta = ''
- end
- atts = pba( atts )
- atts = shelve( atts ) if atts
-
- "#{ sta }#{ oqs }<#{ ht }#{ atts }>#{ content }#{ ht }>#{ oqa }"
-
- end
- end
- end
-
- LINK_RE = /
- (
- ([\s\[{(]|[#{PUNCT}])? # $pre
- " # start
- (#{C}) # $atts
- ([^"\n]+?) # $text
- \s?
- (?:\(([^)]+?)\)(?="))? # $title
- ":
- ( # $url
- (\/|[a-zA-Z]+:\/\/|www\.|mailto:) # $proto
- [[:alnum:]_\/]\S+?
- )
- (\/)? # $slash
- ([^[:alnum:]_\=\/;\(\)]*?) # $post
- )
- (?=<|\s|$)
- /x
-#"
- def inline_textile_link( text )
- text.gsub!( LINK_RE ) do |m|
- all,pre,atts,text,title,url,proto,slash,post = $~[1..9]
- if text.include?('
')
- all
- else
- url, url_title = check_refs( url )
- title ||= url_title
-
- # Idea below : an URL with unbalanced parethesis and
- # ending by ')' is put into external parenthesis
- if ( url[-1]==?) and ((url.count("(") - url.count(")")) < 0 ) )
- url=url[0..-2] # discard closing parenth from url
- post = ")"+post # add closing parenth to post
- end
- atts = pba( atts )
- atts = " href=\"#{ htmlesc url }#{ slash }\"#{ atts }"
- atts << " title=\"#{ htmlesc title }\"" if title
- atts = shelve( atts ) if atts
-
- external = (url =~ /^https?:\/\//) ? ' class="external"' : ''
-
- "#{ pre }#{ text }#{ post }"
- end
- end
- end
-
- MARKDOWN_REFLINK_RE = /
- \[([^\[\]]+)\] # $text
- [ ]? # opt. space
- (?:\n[ ]*)? # one optional newline followed by spaces
- \[(.*?)\] # $id
- /x
-
- def inline_markdown_reflink( text )
- text.gsub!( MARKDOWN_REFLINK_RE ) do |m|
- text, id = $~[1..2]
-
- if id.empty?
- url, title = check_refs( text )
- else
- url, title = check_refs( id )
- end
-
- atts = " href=\"#{ url }\""
- atts << " title=\"#{ title }\"" if title
- atts = shelve( atts )
-
- "#{ text }"
- end
- end
-
- MARKDOWN_LINK_RE = /
- \[([^\[\]]+)\] # $text
- \( # open paren
- [ \t]* # opt space
- (.+?)>? # $href
- [ \t]* # opt space
- (?: # whole title
- (['"]) # $quote
- (.*?) # $title
- \3 # matching quote
- )? # title is optional
- \)
- /x
-
- def inline_markdown_link( text )
- text.gsub!( MARKDOWN_LINK_RE ) do |m|
- text, url, quote, title = $~[1..4]
-
- atts = " href=\"#{ url }\""
- atts << " title=\"#{ title }\"" if title
- atts = shelve( atts )
-
- "#{ text }"
- end
- end
-
- TEXTILE_REFS_RE = /(^ *)\[([^\[\n]+?)\](#{HYPERLINK})(?=\s|$)/
- MARKDOWN_REFS_RE = /(^ *)\[([^\n]+?)\]:\s+(#{HYPERLINK})>?(?:\s+"((?:[^"]|\\")+)")?(?=\s|$)/m
-
- def refs( text )
- @rules.each do |rule_name|
- method( rule_name ).call( text ) if rule_name.to_s.match /^refs_/
- end
- end
-
- def refs_textile( text )
- text.gsub!( TEXTILE_REFS_RE ) do |m|
- flag, url = $~[2..3]
- @urlrefs[flag.downcase] = [url, nil]
- nil
- end
- end
-
- def refs_markdown( text )
- text.gsub!( MARKDOWN_REFS_RE ) do |m|
- flag, url = $~[2..3]
- title = $~[6]
- @urlrefs[flag.downcase] = [url, title]
- nil
- end
- end
-
- def check_refs( text )
- ret = @urlrefs[text.downcase] if text
- ret || [text, nil]
- end
-
- IMAGE_RE = /
- (>|\s|^) # start of line?
- \! # opening
- (\<|\=|\>)? # optional alignment atts
- (#{C}) # optional style,class atts
- (?:\. )? # optional dot-space
- ([^\s(!]+?) # presume this is the src
- \s? # optional space
- (?:\(((?:[^\(\)]|\([^\)]+\))+?)\))? # optional title
- \! # closing
- (?::#{ HYPERLINK })? # optional href
- /x
-
- def inline_textile_image( text )
- text.gsub!( IMAGE_RE ) do |m|
- stln,algn,atts,url,title,href,href_a1,href_a2 = $~[1..8]
- htmlesc title
- atts = pba( atts )
- atts = " src=\"#{ htmlesc url.dup }\"#{ atts }"
- atts << " title=\"#{ title }\"" if title
- atts << " alt=\"#{ title }\""
- # size = @getimagesize($url);
- # if($size) $atts.= " $size[3]";
-
- href, alt_title = check_refs( href ) if href
- url, url_title = check_refs( url )
-
- out = ''
- out << "" if href
- out << "
"
- out << "#{ href_a1 }#{ href_a2 }" if href
-
- if algn
- algn = h_align( algn )
- if stln == ""
- out = "
#{ out }"
- else
- out = "#{ stln }
#{ out }"
- end
- else
- out = stln + out
- end
-
- out
- end
- end
-
- def shelve( val )
- @shelf << val
- " :redsh##{ @shelf.length }:"
- end
-
- def retrieve( text )
- @shelf.each_with_index do |r, i|
- text.gsub!( " :redsh##{ i + 1 }:", r )
- end
- end
-
- def incoming_entities( text )
- ## turn any incoming ampersands into a dummy character for now.
- ## This uses a negative lookahead for alphanumerics followed by a semicolon,
- ## implying an incoming html entity, to be skipped
-
- text.gsub!( /&(?![#a-z0-9]+;)/i, "x%x%" )
- end
-
- def no_textile( text )
- text.gsub!( /(^|\s)==([^=]+.*?)==(\s|$)?/,
- '\1\2 \3' )
- text.gsub!( /^ *==([^=]+.*?)==/m,
- '\1\2 \3' )
- end
-
- def clean_white_space( text )
- # normalize line breaks
- text.gsub!( /\r\n/, "\n" )
- text.gsub!( /\r/, "\n" )
- text.gsub!( /\t/, ' ' )
- text.gsub!( /^ +$/, '' )
- text.gsub!( /\n{3,}/, "\n\n" )
- text.gsub!( /"$/, "\" " )
-
- # if entire document is indented, flush
- # to the left side
- flush_left text
- end
-
- def flush_left( text )
- indt = 0
- if text =~ /^ /
- while text !~ /^ {#{indt}}\S/
- indt += 1
- end unless text.empty?
- if indt.nonzero?
- text.gsub!( /^ {#{indt}}/, '' )
- end
- end
- end
-
- def footnote_ref( text )
- text.gsub!( /\b\[([0-9]+?)\](\s)?/,
- '\1\2' )
- end
-
- OFFTAGS = /(code|pre|kbd|notextile)/
- OFFTAG_MATCH = /(?:(<\/#{ OFFTAGS }>)|(<#{ OFFTAGS }[^>]*>))(.*?)(?=<\/?#{ OFFTAGS }\W|\Z)/mi
- OFFTAG_OPEN = /<#{ OFFTAGS }/
- OFFTAG_CLOSE = /<\/?#{ OFFTAGS }/
- HASTAG_MATCH = /(<\/?\w[^\n]*?>)/m
- ALLTAG_MATCH = /(<\/?\w[^\n]*?>)|.*?(?=<\/?\w[^\n]*?>|$)/m
-
- def glyphs_textile( text, level = 0 )
- if text !~ HASTAG_MATCH
- pgl text
- footnote_ref text
- else
- codepre = 0
- text.gsub!( ALLTAG_MATCH ) do |line|
- ## matches are off if we're between , etc.
- if $1
- if line =~ OFFTAG_OPEN
- codepre += 1
- elsif line =~ OFFTAG_CLOSE
- codepre -= 1
- codepre = 0 if codepre < 0
- end
- elsif codepre.zero?
- glyphs_textile( line, level + 1 )
- else
- htmlesc( line, :NoQuotes )
- end
- # p [level, codepre, line]
-
- line
- end
- end
- end
-
- def rip_offtags( text, escape_aftertag=true, escape_line=true )
- if text =~ /<.*>/
- ## strip and encode content
- codepre, used_offtags = 0, {}
- text.gsub!( OFFTAG_MATCH ) do |line|
- if $3
- first, offtag, aftertag = $3, $4, $5
- codepre += 1
- used_offtags[offtag] = true
- if codepre - used_offtags.length > 0
- htmlesc( line, :NoQuotes ) if escape_line
- @pre_list.last << line
- line = ""
- else
- ### htmlesc is disabled between CODE tags which will be parsed with highlighter
- ### Regexp in formatter.rb is : /\s?(.+)/m
- ### NB: some changes were made not to use $N variables, because we use "match"
- ### and it breaks following lines
- htmlesc( aftertag, :NoQuotes ) if aftertag && escape_aftertag && !first.match(//)
- line = ""
- first.match(/<#{ OFFTAGS }([^>]*)>/)
- tag = $1
- $2.to_s.match(/(class\=("[^"]+"|'[^']+'))/i)
- tag << " #{$1}" if $1
- @pre_list << "<#{ tag }>#{ aftertag }"
- end
- elsif $1 and codepre > 0
- if codepre - used_offtags.length > 0
- htmlesc( line, :NoQuotes ) if escape_line
- @pre_list.last << line
- line = ""
- end
- codepre -= 1 unless codepre.zero?
- used_offtags = {} if codepre.zero?
- end
- line
- end
- end
- text
- end
-
- def smooth_offtags( text )
- unless @pre_list.empty?
- ## replace content
- text.gsub!( // ) { @pre_list[$1.to_i] }
- end
- end
-
- def inline( text )
- [/^inline_/, /^glyphs_/].each do |meth_re|
- @rules.each do |rule_name|
- method( rule_name ).call( text ) if rule_name.to_s.match( meth_re )
- end
- end
- end
-
- def h_align( text )
- H_ALGN_VALS[text]
- end
-
- def v_align( text )
- V_ALGN_VALS[text]
- end
-
- def textile_popup_help( name, windowW, windowH )
- ' ' + name + '
'
- end
-
- # HTML cleansing stuff
- BASIC_TAGS = {
- 'a' => ['href', 'title'],
- 'img' => ['src', 'alt', 'title'],
- 'br' => [],
- 'i' => nil,
- 'u' => nil,
- 'b' => nil,
- 'pre' => nil,
- 'kbd' => nil,
- 'code' => ['lang'],
- 'cite' => nil,
- 'strong' => nil,
- 'em' => nil,
- 'ins' => nil,
- 'sup' => nil,
- 'sub' => nil,
- 'del' => nil,
- 'table' => nil,
- 'tr' => nil,
- 'td' => ['colspan', 'rowspan'],
- 'th' => nil,
- 'ol' => nil,
- 'ul' => nil,
- 'li' => nil,
- 'p' => nil,
- 'h1' => nil,
- 'h3' => nil,
- 'h3' => nil,
- 'h4' => nil,
- 'h5' => nil,
- 'h6' => nil,
- 'blockquote' => ['cite']
- }
-
- def clean_html( text, tags = BASIC_TAGS )
- text.gsub!( /]*)>/ ) do
- raw = $~
- tag = raw[2].downcase
- if tags.has_key? tag
- pcs = [tag]
- tags[tag].each do |prop|
- ['"', "'", ''].each do |q|
- q2 = ( q != '' ? q : '\s' )
- if raw[3] =~ /#{prop}\s*=\s*#{q}([^#{q2}]+)#{q}/i
- attrv = $1
- next if prop == 'src' and attrv =~ %r{^(?!http)\w+:}
- pcs << "#{prop}=\"#{$1.gsub('"', '\\"')}\""
- break
- end
- end
- end if tags[tag]
- "<#{raw[1]}#{pcs.join " "}>"
- else
- " "
- end
- end
- end
-
- ALLOWED_TAGS = %w(redpre pre code notextile)
-
- def escape_html_tags(text)
- text.gsub!(%r{<(\/?([!\w]+)[^<>\n]*)(>?)}) {|m| ALLOWED_TAGS.include?($2) ? "<#{$1}#{$3}" : "<#{$1}#{'>' unless $3.blank?}" }
- end
-end
-
diff --git a/trustie2/lib/redmine.rb b/trustie2/lib/redmine.rb
deleted file mode 100644
index 138ab7281..000000000
--- a/trustie2/lib/redmine.rb
+++ /dev/null
@@ -1,275 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'redmine/core_ext'
-
-begin
- require 'RMagick' unless Object.const_defined?(:Magick)
-rescue LoadError
- # RMagick is not available
-end
-
-require 'redmine/scm/base'
-require 'redmine/access_control'
-require 'redmine/access_keys'
-require 'redmine/activity'
-require 'redmine/activity/fetcher'
-require 'redmine/ciphering'
-require 'redmine/codeset_util'
-require 'redmine/custom_field_format'
-require 'redmine/i18n'
-require 'redmine/menu_manager'
-require 'redmine/notifiable'
-require 'redmine/platform'
-require 'redmine/mime_type'
-require 'redmine/notifiable'
-require 'redmine/search'
-require 'redmine/syntax_highlighting'
-require 'redmine/thumbnail'
-require 'redmine/unified_diff'
-require 'redmine/utils'
-require 'redmine/version'
-
-require 'redmine/default_data/loader'
-require 'redmine/helpers/calendar'
-require 'redmine/helpers/diff'
-require 'redmine/helpers/time_report'
-require 'redmine/views/other_formats_builder'
-require 'redmine/views/labelled_form_builder'
-require 'redmine/views/builders'
-
-require 'redmine/themes'
-require 'redmine/hook'
-require 'redmine/plugin'
-
-if RUBY_VERSION < '1.9'
- require 'fastercsv'
-else
- require 'csv'
- FCSV = CSV
-end
-
-Redmine::Scm::Base.add "Subversion"
-Redmine::Scm::Base.add "Darcs"
-Redmine::Scm::Base.add "Mercurial"
-Redmine::Scm::Base.add "Cvs"
-Redmine::Scm::Base.add "Bazaar"
-Redmine::Scm::Base.add "Git"
-Redmine::Scm::Base.add "Filesystem"
-
-Redmine::CustomFieldFormat.map do |fields|
- fields.register 'string'
- fields.register 'text'
- fields.register 'int', :label => :label_integer
- fields.register 'float'
- fields.register 'list'
- fields.register 'date'
- fields.register 'bool', :label => :label_boolean
- fields.register 'user', :only => %w(Issue TimeEntry Version Project), :edit_as => 'list'
- fields.register 'version', :only => %w(Issue TimeEntry Version Project), :edit_as => 'list'
-end
-
-#by young
-Redmine::MenuManager.map :top_menu do |menu|
- menu.push :home, {:host => Setting.user_domain}
- menu.push :course_practice, {:controller => 'projects', :action => 'course', :project_type => 1}
- menu.push :project_deposit, { :controller => 'projects', :action => 'index', :project_type => 0}, :caption => :label_project_deposit
- menu.push :software_user, {:controller => 'users', :action => 'index'}
- menu.push :contest_innovate, {:controller => 'bids', :action => 'contest', :project_type => 1}
- menu.push :requirement_enterprise, {:controller => 'bids', :action => 'index'}
- menu.push :project_module_forums, :forums_path
- menu.push :stores_index, :stores_path
-
-
- # menu.push :investor, :home_path
- # menu.push :theme, :home_path
- # menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
- # menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
- # menu.push :help, Redmine::Info.help_url, :last => true
-end
-#end
-
-# by huang
-# Redmine::MenuManager.map :top_home_menu do |menu|
- # menu.push :home, :home_path
- # menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural
- # menu.push :developer, {:controller => 'users', :action => 'index'}
- # menu.push :investor, :home_path
- # menu.push :theme, :home_path
- # menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
- # menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
- # menu.push :help, Redmine::Info.help_url, :last => true
-# end
-
-# Redmine::MenuManager.map :top_enterprise_menu do |menu|
- # menu.push :home, :home_path
- # menu.push :requirement, {:controller => 'bids', :action => 'index', :project_type => 0 }
- # menu.push :projects, { :controller => 'projects', :action => 'index', :project_type => 0 }, :caption => :label_project_plural
-#
- # menu.push :developer, {:controller => 'users', :action => 'index', :project_type => 0 }
- # menu.push :college_into, {:controller=>'projects', :action=>'course_enterprise', :project_type => 1 }
- # # menu.push :investor, :home_path
- # # menu.push :theme, :home_path
- # # menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
- # # menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
- # # menu.push :help, Redmine::Info.help_url, :last => true
-# end
-
-# Redmine::MenuManager.map :top_college_menu do |menu|
- # menu.push :home, :home_path
- # menu.push :new_course, {:controller => 'projects', :action => 'course', :project_type => 1}
- # menu.push :new_homework, {:controller => 'bids', :action => 'index', :project_type => 1 }
- # menu.push :new_contest, {:controller => 'bids', :action => 'contest', :project_type => 1}
- # menu.push :projects, { :controller => 'projects', :action => 'index', :project_type => 0 }, :caption => :label_project_plural
- # menu.push :developer, {:controller => 'users', :action => 'index', :project_type => 1 }
- # menu.push :enterprise_into, {:controller=>'projects', :action=>'enterprise_course', :project_type => 0 }
- # menu.push :investor, :home_path
- # menu.push :theme, :home_path
- # menu.push :my_page, { :controller => 'my', :action => 'page' }, :if => Proc.new { User.current.logged? }
- # menu.push :administration, { :controller => 'admin', :action => 'index' }, :if => Proc.new { User.current.admin? }, :last => true
- # menu.push :help, Redmine::Info.help_url, :last => true
-# end
-# end
-
-Redmine::MenuManager.map :account_menu do |menu|
- menu.push :login, {:controller => 'account', :action => 'login'}, :if => Proc.new { !User.current.logged? }
- menu.push :register, {:controller => 'account', :action => 'register'}, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
- # menu.push :my_account, { :controller => 'my', :action => 'account' }, :if => Proc.new { User.current.logged? }
- menu.push :logout, {:controller => 'account', :action => 'logout'}, :html => {:method => 'post'}, :if => Proc.new { User.current.logged? }
-end
-########fq
-Redmine::MenuManager.map :bid_menu do |menu|
- menu.push :respond, { :controller => 'bids', :action => 'show' }, :caption => :label_user_response
- menu.push :project, { :controller => 'bids', :action => 'show_project', :host => Setting.project_domain }, :caption => :label_bidding_project
- # menu.push :result, { :controller => 'bids', :action => 'show_results' },
- # :caption => :label_bidding_results,:if => Proc.new{ |p| User.current.id == p }
-end
-###new add by linchun
-Redmine::MenuManager.map :contest_menu do |menu|
- menu.push :respond, :show_contest_contest_path, :caption => :label_user_response
- #menu.push :project, :show_project_contest_path, :caption => :label_contest_project
- #menu.push :application, :show_softapplication_contest_path, :caption => :label_contest_application
- menu.push :attendingcontest, {:controller => 'contests', :action => 'show_attendingcontest'}, :caption => :label_attending_contest
- # menu.push :contestnotification, {:controller => 'contests', :action => 'show_notification'}, :caption => :label_contest_notification
- # menu.push :attendingcontest, :show_attendingcontest_contest_path, :caption => :label_attendin,g_contest
- # menu.push :result, { :controller => 'bids', :action => 'show_results' },
- # :caption => :label_bidding_results,:if => Proc.new{ |p| User.current.id == p }
-end
-
-####
-Redmine::MenuManager.map :application_menu do |menu|
- # Empty
-end
-
-######
-Redmine::MenuManager.map :homework_menu do |menu|
- menu.push :respond, { :controller => 'bids', :action => 'show' }, :caption => :label_homework_response
- menu.push :project, { :controller => 'bids', :action => 'show_project' }, :caption => :label_bidding_homework
-end
-########end
-Redmine::MenuManager.map :admin_menu do |menu|
- menu.push :projects, {:controller => 'admin', :action => 'projects'}, :caption => :label_project_plural
- menu.push :users, {:controller => 'admin', :action => 'users'}, :caption => :label_user_plural
- menu.push :groups, {:controller => 'groups'}, :caption => :label_group_plural
- menu.push :roles, {:controller => 'roles'}, :caption => :label_role_and_permissions
- menu.push :trackers, {:controller => 'trackers'}, :caption => :label_tracker_plural
- menu.push :issue_statuses, {:controller => 'issue_statuses'}, :caption => :label_issue_status_plural,
- :html => {:class => 'issue_statuses'}
- menu.push :workflows, {:controller => 'workflows', :action => 'edit'}, :caption => :label_workflow
- menu.push :custom_fields, {:controller => 'custom_fields'}, :caption => :label_custom_field_plural,
- :html => {:class => 'custom_fields'}
- menu.push :enumerations, {:controller => 'enumerations'}
- menu.push :settings, {:controller => 'settings'}
- menu.push :ldap_authentication, {:controller => 'auth_sources', :action => 'index'},
- :html => {:class => 'server_authentication'}
- menu.push :plugins, {:controller => 'admin', :action => 'plugins'}, :last => true
- menu.push :info, {:controller => 'admin', :action => 'info'}, :caption => :label_information_plural, :last => true
-
-end
-#Modified by young
-Redmine::MenuManager.map :project_menu do |menu|
- menu.push :overview, { :controller => 'projects', :action => 'show' }
-# menu.push :activity, { :controller => 'activities', :action => 'index' }
- #menu.push :roadmap, { :controller => 'versions', :action => 'index' }, :param => :project_id
-# :if => Proc.new { |p| p.shared_versions.any? }
- menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
-# menu.push :new_issue, { :controller => 'issues', :action => 'new', :copy_from => nil }, :param => :project_id, :caption => :label_issue_new,
-# :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
-# menu.push :calendar, { :controller => 'calendars', :action => 'show' }, :param => :project_id, :caption => :label_calendar
- menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
-# menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
-# menu.push :wiki, { :controller => 'wiki', :action => 'show', :id => nil }, :param => :project_id,
-# :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
- menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
- :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
- #menu.push :files, { :controller => 'files', :action => 'index' }, :param => :project_id, :caption => :label_file_new
- menu.push :repository, { :controller => 'repositories', :action => 'show', :repository_id => nil, :path => nil, :rev => nil },
- :if => Proc.new { |p| p.repository && !p.repository.new_record? && !( !User.current.member_of?(p) && p.hidden_repo ) }
- menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
-
-end
-#end
-
-#added by young
-Redmine::MenuManager.map :course_menu do |menu|
- menu.push :overview, { :controller => 'projects', :action => 'show'}
- menu.push :homework, { :controller => 'projects', :action => 'homework' }
-# menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
-# menu.push :files, { :controller => 'files', :action => 'index' }, :caption => :label_file_new, :param => :project_id
- menu.push :repository, { :controller => 'repositories', :action => 'show', :repository_id => nil, :path => nil, :rev => nil, :course => 1 }
- # menu.push :settings, { :controller => 'projects', :action => 'settings', :course => 1 }, :last => true
-
-end
-Redmine::MenuManager.map :user_menu do |menu|
- menu.push :activity, {:controller => 'users', :action => 'show', :host => Setting.user_domain }
- menu.push :user_course, {:controller => 'users', :action => 'user_courses', :host => Setting.course_domain}
- #menu.push :user_homework, {:controller => 'users', :action => 'user_homeworks'} by huang
- menu.push :user_project, {:controller => 'users', :action => 'user_projects', :host => Setting.project_domain}
- # menu.push :requirement_focus, {:controller => 'users', :action => 'watch_bids'} by huang
- menu.push :user_newfeedback, {:controller => 'users', :action => 'user_newfeedback', :host => Setting.user_domain}
-
-end
-Redmine::MenuManager.map :user_enterprise_menu do |menu|
- menu.push :activity, {:controller => 'users', :action => 'show', :host => Setting.user_domain }
-
- menu.push :user_project, {:controller => 'users', :action => 'user_projects', :host => Setting.project_domain}
-
- menu.push :requirement_focus, {:controller => 'users', :action => 'watch_bids', :host => Setting.user_domain}
- menu.push :user_newfeedback, {:controller => 'users', :action => 'user_newfeedback', :host => Setting.user_domain}
-
-end
-Redmine::MenuManager.map :user_menu_self do |menu|
- menu.push :activity, {:controller => 'users', :action => 'show', :host => Setting.project_domain }
- menu.push :user_information, {:controller => 'users', :action => 'info', :host => Setting.user_domain}
- menu.push :user_project, {:controller => 'users', :action => 'user_projects', :host => Setting.project_domain}
- menu.push :requirement_focus, {:controller => 'users', :action => 'watch_bids', :host => Setting.user_domain}
- menu.push :user_newfeedback, {:controller => 'users', :action => 'user_newfeedback', :host => Setting.user_domain}
-
-end
-#end
-
-Redmine::Search.map do |search|
- search.register :issues
- search.register :news
- search.register :documents
- search.register :changesets
- search.register :wiki_pages
- search.register :messages
- search.register :projects
-end
-
-ActionView::Template.register_template_handler :rsb, Redmine::Views::ApiTemplateHandler
diff --git a/trustie2/lib/redmine/access_control.rb b/trustie2/lib/redmine/access_control.rb
deleted file mode 100644
index 7c4a5a5ec..000000000
--- a/trustie2/lib/redmine/access_control.rb
+++ /dev/null
@@ -1,135 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 AccessControl
-
- class << self
- def map
- mapper = Mapper.new
- yield mapper
- @permissions ||= []
- @permissions += mapper.mapped_permissions
- end
-
- def permissions
- @permissions
- end
-
- # Returns the permission of given name or nil if it wasn't found
- # Argument should be a symbol
- def permission(name)
- permissions.detect {|p| p.name == name}
- end
-
- # Returns the actions that are allowed by the permission of given name
- def allowed_actions(permission_name)
- perm = permission(permission_name)
- perm ? perm.actions : []
- end
-
- def public_permissions
- @public_permissions ||= @permissions.select {|p| p.public?}
- end
-
- def members_only_permissions
- @members_only_permissions ||= @permissions.select {|p| p.require_member?}
- end
-
- def loggedin_only_permissions
- @loggedin_only_permissions ||= @permissions.select {|p| p.require_loggedin?}
- end
-
- def read_action?(action)
- if action.is_a?(Symbol)
- perm = permission(action)
- !perm.nil? && perm.read?
- else
- s = "#{action[:controller]}/#{action[:action]}"
- permissions.detect {|p| p.actions.include?(s) && !p.read?}.nil?
- end
- end
-
- def available_project_modules
- @available_project_modules ||= @permissions.collect(&:project_module).uniq.compact
- end
-
- def modules_permissions(modules)
- @permissions.select {|p| p.project_module.nil? || modules.include?(p.project_module.to_s)}
- end
- end
-
- class Mapper
- def initialize
- @project_module = nil
- end
-
- def permission(name, hash, options={})
- @permissions ||= []
- options.merge!(:project_module => @project_module)
- @permissions << Permission.new(name, hash, options)
- end
-
- def project_module(name, options={})
- @project_module = name
- yield self
- @project_module = nil
- end
-
- def mapped_permissions
- @permissions
- end
- end
-
- class Permission
- attr_reader :name, :actions, :project_module
-
- def initialize(name, hash, options)
- @name = name
- @actions = []
- @public = options[:public] || false
- @require = options[:require]
- @read = options[:read] || false
- @project_module = options[:project_module]
- hash.each do |controller, actions|
- if actions.is_a? Array
- @actions << actions.collect {|action| "#{controller}/#{action}"}
- else
- @actions << "#{controller}/#{actions}"
- end
- end
- @actions.flatten!
- end
-
- def public?
- @public
- end
-
- def require_member?
- @require && @require == :member
- end
-
- def require_loggedin?
- @require && (@require == :member || @require == :loggedin)
- end
-
- def read?
- @read
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/access_keys.rb b/trustie2/lib/redmine/access_keys.rb
deleted file mode 100644
index c2f6157d8..000000000
--- a/trustie2/lib/redmine/access_keys.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 AccessKeys
- ACCESSKEYS = {:edit => 'e',
- :preview => 'r',
- :quick_search => 'f',
- :search => '4',
- :new_issue => '7'
- }.freeze unless const_defined?(:ACCESSKEYS)
-
- def self.key_for(action)
- ACCESSKEYS[action]
- end
- end
-end
diff --git a/trustie2/lib/redmine/activity.rb b/trustie2/lib/redmine/activity.rb
deleted file mode 100644
index 27ff52eb7..000000000
--- a/trustie2/lib/redmine/activity.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Activity
-
- mattr_accessor :available_event_types, :default_event_types, :providers
-
- @@available_event_types = []
- @@default_event_types = []
- @@providers = Hash.new {|h,k| h[k]=[] }
-
- class << self
- def map(&block)
- yield self
- end
-
- # Registers an activity provider
- def register(event_type, options={})
- options.assert_valid_keys(:class_name, :default)
-
- event_type = event_type.to_s
- providers = options[:class_name] || event_type.classify
- providers = ([] << providers) unless providers.is_a?(Array)
-
- @@available_event_types << event_type unless @@available_event_types.include?(event_type)
- @@default_event_types << event_type unless options[:default] == false
- @@providers[event_type] += providers
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/activity/fetcher.rb b/trustie2/lib/redmine/activity/fetcher.rb
deleted file mode 100644
index f1cc02ae0..000000000
--- a/trustie2/lib/redmine/activity/fetcher.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Activity
- # Class used to retrieve activity events
- class Fetcher
- attr_reader :user, :project, :scope
-
- # Needs to be unloaded in development mode
- @@constantized_providers = Hash.new {|h,k| h[k] = Redmine::Activity.providers[k].collect {|t| t.constantize } }
-
- def initialize(user, options={})
- options.assert_valid_keys(:project, :with_subprojects, :author)
- @user = user
- @project = options[:project]
- @options = options
-
- @scope = event_types
- end
-
- # Returns an array of available event types
- def event_types
- return @event_types unless @event_types.nil?
-
- @event_types = Redmine::Activity.available_event_types
- @event_types = @event_types.select {|o| @project.self_and_descendants.detect {|p| @user.allowed_to?("view_#{o}".to_sym, p)}} if @project
- @event_types
- end
-
- # Yields to filter the activity scope
- def scope_select(&block)
- @scope = @scope.select {|t| yield t }
- end
-
- # Sets the scope
- # Argument can be :all, :default or an array of event types
- def scope=(s)
- case s
- when :all
- @scope = event_types
- when :default
- default_scope!
- else
- @scope = s & event_types
- end
- end
-
- # Resets the scope to the default scope
- def default_scope!
- @scope = Redmine::Activity.default_event_types
- end
-
- # Returns an array of events for the given date range
- # sorted in reverse chronological order
- def events(from = nil, to = nil, options={})
- e = []
- @options[:limit] = options[:limit]
-
- @scope.each do |event_type|
- constantized_providers(event_type).each do |provider|
- e += provider.find_events(event_type, @user, from, to, @options)
- end
- end
-
- e.sort! {|a,b| b.event_datetime <=> a.event_datetime}
-
- if options[:limit]
- e = e.slice(0, options[:limit])
- end
- e
- end
-
- def events_welcome(from = nil, to = nil, options={})
- e = []
- @options[:limit] = options[:limit]
-
- @scope.each do |event_type|
- constantized_providers(event_type).each do |provider|
- e += provider.find_events1(event_type, @user, from, to, @options)
- end
- end
-
- e.sort! {|a,b| b.event_datetime <=> a.event_datetime}
-
- if options[:limit]
- e = e.slice(0, options[:limit])
- end
- e
- end
-
- private
-
- def constantized_providers(event_type)
- @@constantized_providers[event_type]
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/ciphering.rb b/trustie2/lib/redmine/ciphering.rb
deleted file mode 100644
index c691e23ee..000000000
--- a/trustie2/lib/redmine/ciphering.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Ciphering
- def self.included(base)
- base.extend ClassMethods
- end
-
- class << self
- def encrypt_text(text)
- if cipher_key.blank? || text.blank?
- text
- else
- c = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
- iv = c.random_iv
- c.encrypt
- c.key = cipher_key
- c.iv = iv
- e = c.update(text.to_s)
- e << c.final
- "aes-256-cbc:" + [e, iv].map {|v| Base64.encode64(v).strip}.join('--')
- end
- end
-
- def decrypt_text(text)
- if text && match = text.match(/\Aaes-256-cbc:(.+)\Z/)
- if cipher_key.blank?
- logger.error "Attempt to decrypt a ciphered text with no cipher key configured in config/configuration.yml" if logger
- return text
- end
- text = match[1]
- c = OpenSSL::Cipher::Cipher.new("aes-256-cbc")
- e, iv = text.split("--").map {|s| Base64.decode64(s)}
- c.decrypt
- c.key = cipher_key
- c.iv = iv
- d = c.update(e)
- d << c.final
- else
- text
- end
- end
-
- def cipher_key
- key = Redmine::Configuration['database_cipher_key'].to_s
- key.blank? ? nil : Digest::SHA256.hexdigest(key)
- end
-
- def logger
- Rails.logger
- end
- end
-
- module ClassMethods
- def encrypt_all(attribute)
- transaction do
- all.each do |object|
- clear = object.send(attribute)
- object.send "#{attribute}=", clear
- raise(ActiveRecord::Rollback) unless object.save(:validation => false)
- end
- end ? true : false
- end
-
- def decrypt_all(attribute)
- transaction do
- all.each do |object|
- clear = object.send(attribute)
- object.send :write_attribute, attribute, clear
- raise(ActiveRecord::Rollback) unless object.save(:validation => false)
- end
- end
- end ? true : false
- end
-
- private
-
- # Returns the value of the given ciphered attribute
- def read_ciphered_attribute(attribute)
- Redmine::Ciphering.decrypt_text(read_attribute(attribute))
- end
-
- # Sets the value of the given ciphered attribute
- def write_ciphered_attribute(attribute, value)
- write_attribute(attribute, Redmine::Ciphering.encrypt_text(value))
- end
- end
-end
diff --git a/trustie2/lib/redmine/codeset_util.rb b/trustie2/lib/redmine/codeset_util.rb
deleted file mode 100644
index 45a5c3524..000000000
--- a/trustie2/lib/redmine/codeset_util.rb
+++ /dev/null
@@ -1,161 +0,0 @@
-if RUBY_VERSION < '1.9'
- require 'iconv'
-end
-
-module Redmine
- module CodesetUtil
-
- def self.replace_invalid_utf8(str)
- return str if str.nil?
- if str.respond_to?(:force_encoding)
- str.force_encoding('UTF-8')
- if ! str.valid_encoding?
- str = str.encode("US-ASCII", :invalid => :replace,
- :undef => :replace, :replace => '?').encode("UTF-8")
- end
- elsif RUBY_PLATFORM == 'java'
- begin
- ic = Iconv.new('UTF-8', 'UTF-8')
- str = ic.iconv(str)
- rescue
- str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
- end
- else
- ic = Iconv.new('UTF-8', 'UTF-8')
- txtar = ""
- begin
- txtar += ic.iconv(str)
- rescue Iconv::IllegalSequence
- txtar += $!.success
- str = '?' + $!.failed[1,$!.failed.length]
- retry
- rescue
- txtar += $!.success
- end
- str = txtar
- end
- str
- end
-
- def self.to_utf8(str, encoding)
- return str if str.nil?
- str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
- if str.empty?
- str.force_encoding("UTF-8") if str.respond_to?(:force_encoding)
- return str
- end
- enc = encoding.blank? ? "UTF-8" : encoding
- if str.respond_to?(:force_encoding)
- if enc.upcase != "UTF-8"
- str.force_encoding(enc)
- str = str.encode("UTF-8", :invalid => :replace,
- :undef => :replace, :replace => '?')
- else
- str.force_encoding("UTF-8")
- if ! str.valid_encoding?
- str = str.encode("US-ASCII", :invalid => :replace,
- :undef => :replace, :replace => '?').encode("UTF-8")
- end
- end
- elsif RUBY_PLATFORM == 'java'
- begin
- ic = Iconv.new('UTF-8', enc)
- str = ic.iconv(str)
- rescue
- str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
- end
- else
- ic = Iconv.new('UTF-8', enc)
- txtar = ""
- begin
- txtar += ic.iconv(str)
- rescue Iconv::IllegalSequence
- txtar += $!.success
- str = '?' + $!.failed[1,$!.failed.length]
- retry
- rescue
- txtar += $!.success
- end
- str = txtar
- end
- str
- end
-
- def self.to_utf8_by_setting(str)
- return str if str.nil?
- str = self.to_utf8_by_setting_internal(str)
- if str.respond_to?(:force_encoding)
- str.force_encoding('UTF-8')
- end
- str
- end
-
- def self.to_utf8_by_setting_internal(str)
- return str if str.nil?
- if str.respond_to?(:force_encoding)
- str.force_encoding('ASCII-8BIT')
- end
- return str if str.empty?
- return str if /\A[\r\n\t\x20-\x7e]*\Z/n.match(str) # for us-ascii
- if str.respond_to?(:force_encoding)
- str.force_encoding('UTF-8')
- end
- encodings = Setting.repositories_encodings.split(',').collect(&:strip)
- encodings.each do |encoding|
- if str.respond_to?(:force_encoding)
- begin
- str.force_encoding(encoding)
- utf8 = str.encode('UTF-8')
- return utf8 if utf8.valid_encoding?
- rescue
- # do nothing here and try the next encoding
- end
- else
- begin
- return Iconv.conv('UTF-8', encoding, str)
- rescue Iconv::Failure
- # do nothing here and try the next encoding
- end
- end
- end
- str = self.replace_invalid_utf8(str)
- if str.respond_to?(:force_encoding)
- str.force_encoding('UTF-8')
- end
- str
- end
-
- def self.from_utf8(str, encoding)
- str ||= ''
- if str.respond_to?(:force_encoding)
- str.force_encoding('UTF-8')
- if encoding.upcase != 'UTF-8'
- str = str.encode(encoding, :invalid => :replace,
- :undef => :replace, :replace => '?')
- else
- str = self.replace_invalid_utf8(str)
- end
- elsif RUBY_PLATFORM == 'java'
- begin
- ic = Iconv.new(encoding, 'UTF-8')
- str = ic.iconv(str)
- rescue
- str = str.gsub(%r{[^\r\n\t\x20-\x7e]}, '?')
- end
- else
- ic = Iconv.new(encoding, 'UTF-8')
- txtar = ""
- begin
- txtar += ic.iconv(str)
- rescue Iconv::IllegalSequence
- txtar += $!.success
- str = '?' + $!.failed[1, $!.failed.length]
- retry
- rescue
- txtar += $!.success
- end
- str = txtar
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/configuration.rb b/trustie2/lib/redmine/configuration.rb
deleted file mode 100644
index 6723b777e..000000000
--- a/trustie2/lib/redmine/configuration.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Configuration
-
- # Configuration default values
- @defaults = {
- 'email_delivery' => nil,
- 'max_concurrent_ajax_uploads' => 2
- }
-
- @config = nil
-
- class << self
- # Loads the Redmine configuration file
- # Valid options:
- # * :file: the configuration file to load (default: config/configuration.yml)
- # * :env: the environment to load the configuration for (default: Rails.env)
- def load(options={})
- filename = options[:file] || File.join(Rails.root, 'config', 'configuration.yml')
- env = options[:env] || Rails.env
-
- @config = @defaults.dup
-
- load_deprecated_email_configuration(env)
- if File.file?(filename)
- @config.merge!(load_from_yaml(filename, env))
- end
-
- # Compatibility mode for those who copy email.yml over configuration.yml
- %w(delivery_method smtp_settings sendmail_settings).each do |key|
- if value = @config.delete(key)
- @config['email_delivery'] ||= {}
- @config['email_delivery'][key] = value
- end
- end
-
- if @config['email_delivery']
- ActionMailer::Base.perform_deliveries = true
- @config['email_delivery'].each do |k, v|
- v.symbolize_keys! if v.respond_to?(:symbolize_keys!)
- ActionMailer::Base.send("#{k}=", v)
- end
- end
-
- @config
- end
-
- # Returns a configuration setting
- def [](name)
- load unless @config
- @config[name]
- end
-
- # Yields a block with the specified hash configuration settings
- def with(settings)
- settings.stringify_keys!
- load unless @config
- was = settings.keys.inject({}) {|h,v| h[v] = @config[v]; h}
- @config.merge! settings
- yield if block_given?
- @config.merge! was
- end
-
- private
-
- def load_from_yaml(filename, env)
- yaml = nil
- begin
- yaml = YAML::load_file(filename)
- rescue ArgumentError
- $stderr.puts "Your Redmine configuration file located at #{filename} is not a valid YAML file and could not be loaded."
- exit 1
- end
- conf = {}
- if yaml.is_a?(Hash)
- if yaml['default']
- conf.merge!(yaml['default'])
- end
- if yaml[env]
- conf.merge!(yaml[env])
- end
- else
- $stderr.puts "Your Redmine configuration file located at #{filename} is not a valid Redmine configuration file."
- exit 1
- end
- conf
- end
-
- def load_deprecated_email_configuration(env)
- deprecated_email_conf = File.join(Rails.root, 'config', 'email.yml')
- if File.file?(deprecated_email_conf)
- warn "Storing outgoing emails configuration in config/email.yml is deprecated. You should now store it in config/configuration.yml using the email_delivery setting."
- @config.merge!({'email_delivery' => load_from_yaml(deprecated_email_conf, env)})
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/core_ext.rb b/trustie2/lib/redmine/core_ext.rb
deleted file mode 100644
index 573313e74..000000000
--- a/trustie2/lib/redmine/core_ext.rb
+++ /dev/null
@@ -1 +0,0 @@
-Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].each { |file| require(file) }
diff --git a/trustie2/lib/redmine/core_ext/active_record.rb b/trustie2/lib/redmine/core_ext/active_record.rb
deleted file mode 100644
index ad27a3f03..000000000
--- a/trustie2/lib/redmine/core_ext/active_record.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 ActiveRecord
- module FinderMethods
- def find_ids(*args)
- find_ids_with_associations
- end
-
- private
-
- def find_ids_with_associations
- join_dependency = construct_join_dependency_for_association_find
- relation = construct_relation_for_association_find_ids(join_dependency)
- rows = connection.select_all(relation, 'SQL', relation.bind_values)
- rows.map {|row| row["id"].to_i}
- rescue ThrowResult
- []
- end
-
- def construct_relation_for_association_find_ids(join_dependency)
- relation = except(:includes, :eager_load, :preload, :select).select("#{table_name}.id")
- apply_join_dependency(relation, join_dependency)
- end
- end
-end
-
-class DateValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- before_type_cast = record.attributes_before_type_cast[attribute.to_s]
- if before_type_cast.is_a?(String) && before_type_cast.present?
- # TODO: #*_date_before_type_cast returns a Mysql::Time with ruby1.8+mysql gem
- unless before_type_cast =~ /\A\d{4}-\d{2}-\d{2}( 00:00:00)?\z/ && value
- record.errors.add attribute, :not_a_date
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/core_ext/date.rb b/trustie2/lib/redmine/core_ext/date.rb
deleted file mode 100644
index 9244b5d6e..000000000
--- a/trustie2/lib/redmine/core_ext/date.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require File.dirname(__FILE__) + '/date/calculations'
-
-class Date #:nodoc:
- include Redmine::CoreExtensions::Date::Calculations
-end
diff --git a/trustie2/lib/redmine/core_ext/date/calculations.rb b/trustie2/lib/redmine/core_ext/date/calculations.rb
deleted file mode 100644
index 0372e8ac1..000000000
--- a/trustie2/lib/redmine/core_ext/date/calculations.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 #:nodoc:
- module CoreExtensions #:nodoc:
- module Date #:nodoc:
- # Custom date calculations
- module Calculations
- # Returns difference with specified date in months
- def months_ago(date = self.class.today)
- (date.year - self.year)*12 + (date.month - self.month)
- end
-
- # Returns difference with specified date in weeks
- def weeks_ago(date = self.class.today)
- (date.year - self.year)*52 + (date.cweek - self.cweek)
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/core_ext/string.rb b/trustie2/lib/redmine/core_ext/string.rb
deleted file mode 100644
index c865284ac..000000000
--- a/trustie2/lib/redmine/core_ext/string.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require File.dirname(__FILE__) + '/string/conversions'
-require File.dirname(__FILE__) + '/string/inflections'
-
-class String #:nodoc:
- include Redmine::CoreExtensions::String::Conversions
- include Redmine::CoreExtensions::String::Inflections
-
- def is_binary_data?
- ( self.count( "^ -~", "^\r\n" ).fdiv(self.size) > 0.3 || self.index( "\x00" ) ) unless empty?
- end
-end
diff --git a/trustie2/lib/redmine/core_ext/string/conversions.rb b/trustie2/lib/redmine/core_ext/string/conversions.rb
deleted file mode 100644
index 7fbc02ee6..000000000
--- a/trustie2/lib/redmine/core_ext/string/conversions.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 #:nodoc:
- module CoreExtensions #:nodoc:
- module String #:nodoc:
- # Custom string conversions
- module Conversions
- # Parses hours format and returns a float
- def to_hours
- s = self.dup
- s.strip!
- if s =~ %r{^(\d+([.,]\d+)?)h?$}
- s = $1
- else
- # 2:30 => 2.5
- s.gsub!(%r{^(\d+):(\d+)$}) { $1.to_i + $2.to_i / 60.0 }
- # 2h30, 2h, 30m => 2.5, 2, 0.5
- s.gsub!(%r{^((\d+)\s*(h|hours?))?\s*((\d+)\s*(m|min)?)?$}i) { |m| ($1 || $4) ? ($2.to_i + $5.to_i / 60.0) : m[0] }
- end
- # 2,5 => 2.5
- s.gsub!(',', '.')
- begin; Kernel.Float(s); rescue; nil; end
- end
-
- # Object#to_a removed in ruby1.9
- if RUBY_VERSION > '1.9'
- def to_a
- [self.dup]
- end
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/core_ext/string/inflections.rb b/trustie2/lib/redmine/core_ext/string/inflections.rb
deleted file mode 100644
index ecbbe2789..000000000
--- a/trustie2/lib/redmine/core_ext/string/inflections.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 #:nodoc:
- module CoreExtensions #:nodoc:
- module String #:nodoc:
- # Custom string inflections
- module Inflections
- def with_leading_slash
- starts_with?('/') ? self : "/#{ self }"
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/custom_field_format.rb b/trustie2/lib/redmine/custom_field_format.rb
deleted file mode 100644
index f7cd5d1c6..000000000
--- a/trustie2/lib/redmine/custom_field_format.rb
+++ /dev/null
@@ -1,108 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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
- class CustomFieldFormat
- include Redmine::I18n
-
- cattr_accessor :available
- @@available = {}
-
- attr_accessor :name, :order, :label, :edit_as, :class_names
-
- def initialize(name, options={})
- self.name = name
- self.label = options[:label] || "label_#{name}".to_sym
- self.order = options[:order] || self.class.available_formats.size
- self.edit_as = options[:edit_as] || name
- self.class_names = options[:only]
- end
-
- def format(value)
- send "format_as_#{name}", value
- end
-
- def format_as_date(value)
- begin; format_date(value.to_date); rescue; value end
- end
-
- def format_as_bool(value)
- l(value == "1" ? :general_text_Yes : :general_text_No)
- end
-
- ['string','text','int','float','list'].each do |name|
- define_method("format_as_#{name}") {|value|
- return value
- }
- end
-
- ['user', 'version'].each do |name|
- define_method("format_as_#{name}") {|value|
- return value.blank? ? "" : name.classify.constantize.find_by_id(value.to_i).to_s
- }
- end
-
- class << self
- def map(&block)
- yield self
- end
-
- # Registers a custom field format
- def register(*args)
- custom_field_format = args.first
- unless custom_field_format.is_a?(Redmine::CustomFieldFormat)
- custom_field_format = Redmine::CustomFieldFormat.new(*args)
- end
- @@available[custom_field_format.name] = custom_field_format unless @@available.keys.include?(custom_field_format.name)
- end
-
- def available_formats
- @@available.keys
- end
-
- def find_by_name(name)
- @@available[name.to_s]
- end
-
- def label_for(name)
- format = @@available[name.to_s]
- format.label if format
- end
-
- # Return an array of custom field formats which can be used in select_tag
- def as_select(class_name=nil)
- fields = @@available.values
- fields = fields.select {|field| field.class_names.nil? || field.class_names.include?(class_name)}
- fields.sort {|a,b|
- a.order <=> b.order
- }.collect {|custom_field_format|
- [ l(custom_field_format.label), custom_field_format.name ]
- }
- end
-
- def format_value(value, field_format)
- return "" unless value && !value.empty?
-
- if format_type = find_by_name(field_format)
- format_type.format(value)
- else
- value
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/default_data/loader.rb b/trustie2/lib/redmine/default_data/loader.rb
deleted file mode 100644
index 21e421d05..000000000
--- a/trustie2/lib/redmine/default_data/loader.rb
+++ /dev/null
@@ -1,177 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 DefaultData
- class DataAlreadyLoaded < Exception; end
-
- module Loader
- include Redmine::I18n
-
- class << self
- # Returns true if no data is already loaded in the database
- # otherwise false
- def no_data?
- !Role.where(:builtin => 0).exists? &&
- !Tracker.exists? &&
- !IssueStatus.exists? &&
- !Enumeration.exists?
- end
-
- # Loads the default data
- # Raises a RecordNotSaved exception if something goes wrong
- def load(lang=nil)
- raise DataAlreadyLoaded.new("Some configuration data is already loaded.") unless no_data?
- set_language_if_valid(lang)
-
- Role.transaction do
- # Roles
- manager = Role.create! :name => l(:default_role_manager),
- :issues_visibility => 'all',
- :position => 1
- manager.permissions = manager.setable_permissions.collect {|p| p.name}
- manager.save!
-
- developer = Role.create! :name => l(:default_role_developer),
- :position => 2,
- :permissions => [:manage_versions,
- :manage_categories,
- :view_issues,
- :add_issues,
- :edit_issues,
- :view_private_notes,
- :set_notes_private,
- :manage_issue_relations,
- :manage_subtasks,
- :add_issue_notes,
- :save_queries,
- :log_time,
- :view_time_entries,
- :comment_news,
- :view_documents,
- :view_wiki_pages,
- :view_wiki_edits,
- :edit_wiki_pages,
- :delete_wiki_pages,
- :add_messages,
- :edit_own_messages,
- :view_files,
- :manage_files,
- :browse_repository,
- :view_changesets,
- :commit_access,
- :manage_related_issues]
-
- reporter = Role.create! :name => l(:default_role_reporter),
- :position => 3,
- :permissions => [:view_issues,
- :add_issues,
- :add_issue_notes,
- :save_queries,
- :log_time,
- :view_time_entries,
- :comment_news,
- :view_documents,
- :view_wiki_pages,
- :view_wiki_edits,
- :add_messages,
- :edit_own_messages,
- :view_files,
- :browse_repository,
- :view_changesets]
-
- Role.non_member.update_attribute :permissions, [:view_issues,
- :add_issues,
- :add_issue_notes,
- :save_queries,
- :view_time_entries,
- :comment_news,
- :view_documents,
- :view_wiki_pages,
- :view_wiki_edits,
- :add_messages,
- :view_files,
- :browse_repository,
- :view_changesets]
-
- Role.anonymous.update_attribute :permissions, [:view_issues,
- :view_time_entries,
- :view_documents,
- :view_wiki_pages,
- :view_wiki_edits,
- :view_files,
- :browse_repository,
- :view_changesets]
-
- # Trackers
- Tracker.create!(:name => l(:default_tracker_bug), :is_in_chlog => true, :is_in_roadmap => false, :position => 1)
- Tracker.create!(:name => l(:default_tracker_feature), :is_in_chlog => true, :is_in_roadmap => true, :position => 2)
- Tracker.create!(:name => l(:default_tracker_support), :is_in_chlog => false, :is_in_roadmap => false, :position => 3)
-
- # Issue statuses
- new = IssueStatus.create!(:name => l(:default_issue_status_new), :is_closed => false, :is_default => true, :position => 1)
- in_progress = IssueStatus.create!(:name => l(:default_issue_status_in_progress), :is_closed => false, :is_default => false, :position => 2)
- resolved = IssueStatus.create!(:name => l(:default_issue_status_resolved), :is_closed => false, :is_default => false, :position => 3)
- feedback = IssueStatus.create!(:name => l(:default_issue_status_feedback), :is_closed => false, :is_default => false, :position => 4)
- closed = IssueStatus.create!(:name => l(:default_issue_status_closed), :is_closed => true, :is_default => false, :position => 5)
- rejected = IssueStatus.create!(:name => l(:default_issue_status_rejected), :is_closed => true, :is_default => false, :position => 6)
-
- # Workflow
- Tracker.all.each { |t|
- IssueStatus.all.each { |os|
- IssueStatus.all.each { |ns|
- WorkflowTransition.create!(:tracker_id => t.id, :role_id => manager.id, :old_status_id => os.id, :new_status_id => ns.id) unless os == ns
- }
- }
- }
-
- Tracker.all.each { |t|
- [new, in_progress, resolved, feedback].each { |os|
- [in_progress, resolved, feedback, closed].each { |ns|
- WorkflowTransition.create!(:tracker_id => t.id, :role_id => developer.id, :old_status_id => os.id, :new_status_id => ns.id) unless os == ns
- }
- }
- }
-
- Tracker.all.each { |t|
- [new, in_progress, resolved, feedback].each { |os|
- [closed].each { |ns|
- WorkflowTransition.create!(:tracker_id => t.id, :role_id => reporter.id, :old_status_id => os.id, :new_status_id => ns.id) unless os == ns
- }
- }
- WorkflowTransition.create!(:tracker_id => t.id, :role_id => reporter.id, :old_status_id => resolved.id, :new_status_id => feedback.id)
- }
-
- # Enumerations
- IssuePriority.create!(:name => l(:default_priority_low), :position => 1)
- IssuePriority.create!(:name => l(:default_priority_normal), :position => 2, :is_default => true)
- IssuePriority.create!(:name => l(:default_priority_high), :position => 3)
- IssuePriority.create!(:name => l(:default_priority_urgent), :position => 4)
- IssuePriority.create!(:name => l(:default_priority_immediate), :position => 5)
-
- DocumentCategory.create!(:name => l(:default_doc_category_user), :position => 1)
- DocumentCategory.create!(:name => l(:default_doc_category_tech), :position => 2)
-
- TimeEntryActivity.create!(:name => l(:default_activity_design), :position => 1)
- TimeEntryActivity.create!(:name => l(:default_activity_development), :position => 2)
- end
- true
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/helpers/calendar.rb b/trustie2/lib/redmine/helpers/calendar.rb
deleted file mode 100644
index fa01b2f42..000000000
--- a/trustie2/lib/redmine/helpers/calendar.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Helpers
-
- # Simple class to compute the start and end dates of a calendar
- class Calendar
- include Redmine::I18n
- attr_reader :startdt, :enddt
-
- def initialize(date, lang = current_language, period = :month)
- @date = date
- @events = []
- @ending_events_by_days = {}
- @starting_events_by_days = {}
- set_language_if_valid lang
- case period
- when :month
- @startdt = Date.civil(date.year, date.month, 1)
- @enddt = (@startdt >> 1)-1
- # starts from the first day of the week
- @startdt = @startdt - (@startdt.cwday - first_wday)%7
- # ends on the last day of the week
- @enddt = @enddt + (last_wday - @enddt.cwday)%7
- when :week
- @startdt = date - (date.cwday - first_wday)%7
- @enddt = date + (last_wday - date.cwday)%7
- else
- raise 'Invalid period'
- end
- end
-
- # Sets calendar events
- def events=(events)
- @events = events
- @ending_events_by_days = @events.group_by {|event| event.due_date}
- @starting_events_by_days = @events.group_by {|event| event.start_date}
- end
-
- # Returns events for the given day
- def events_on(day)
- ((@ending_events_by_days[day] || []) + (@starting_events_by_days[day] || [])).uniq
- end
-
- # Calendar current month
- def month
- @date.month
- end
-
- # Return the first day of week
- # 1 = Monday ... 7 = Sunday
- def first_wday
- case Setting.start_of_week.to_i
- when 1
- @first_dow ||= (1 - 1)%7 + 1
- when 6
- @first_dow ||= (6 - 1)%7 + 1
- when 7
- @first_dow ||= (7 - 1)%7 + 1
- else
- @first_dow ||= (l(:general_first_day_of_week).to_i - 1)%7 + 1
- end
- end
-
- def last_wday
- @last_dow ||= (first_wday + 5)%7 + 1
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/helpers/diff.rb b/trustie2/lib/redmine/helpers/diff.rb
deleted file mode 100644
index 537bfa05d..000000000
--- a/trustie2/lib/redmine/helpers/diff.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Helpers
- class Diff
- include ERB::Util
- include ActionView::Helpers::TagHelper
- include ActionView::Helpers::TextHelper
- attr_reader :diff, :words
-
- def initialize(content_to, content_from)
- @words = content_to.to_s.split(/(\s+)/)
- @words = @words.select {|word| word != ' '}
- words_from = content_from.to_s.split(/(\s+)/)
- words_from = words_from.select {|word| word != ' '}
- @diff = words_from.diff @words
- end
-
- def to_html
- words = self.words.collect{|word| h(word)}
- words_add = 0
- words_del = 0
- dels = 0
- del_off = 0
- diff.diffs.each do |diff|
- add_at = nil
- add_to = nil
- del_at = nil
- deleted = ""
- diff.each do |change|
- pos = change[1]
- if change[0] == "+"
- add_at = pos + dels unless add_at
- add_to = pos + dels
- words_add += 1
- else
- del_at = pos unless del_at
- deleted << ' ' unless deleted.empty?
- deleted << h(change[2])
- words_del += 1
- end
- end
- if add_at
- words[add_at] = ''.html_safe + words[add_at]
- words[add_to] = words[add_to] + ''.html_safe
- end
- if del_at
- words.insert del_at - del_off + dels + words_add, ''.html_safe + deleted + ''.html_safe
- dels += 1
- del_off += words_del
- words_del = 0
- end
- end
- words.join(' ').html_safe
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/helpers/time_report.rb b/trustie2/lib/redmine/helpers/time_report.rb
deleted file mode 100644
index 09093dc95..000000000
--- a/trustie2/lib/redmine/helpers/time_report.rb
+++ /dev/null
@@ -1,151 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Helpers
- class TimeReport
- attr_reader :criteria, :columns, :hours, :total_hours, :periods
-
- def initialize(project, issue, criteria, columns, time_entry_scope)
- @project = project
- @issue = issue
-
- @criteria = criteria || []
- @criteria = @criteria.select{|criteria| available_criteria.has_key? criteria}
- @criteria.uniq!
- @criteria = @criteria[0,3]
-
- @columns = (columns && %w(year month week day).include?(columns)) ? columns : 'month'
- @scope = time_entry_scope
-
- run
- end
-
- def available_criteria
- @available_criteria || load_available_criteria
- end
-
- private
-
- def run
- unless @criteria.empty?
- time_columns = %w(tyear tmonth tweek spent_on)
- @hours = []
- @scope.sum(:hours,
- :include => [:issue, :activity],
- :group => @criteria.collect{|criteria| @available_criteria[criteria][:sql]} + time_columns,
- :joins => @criteria.collect{|criteria| @available_criteria[criteria][:joins]}.compact).each do |hash, hours|
- h = {'hours' => hours}
- (@criteria + time_columns).each_with_index do |name, i|
- h[name] = hash[i]
- end
- @hours << h
- end
-
- @hours.each do |row|
- case @columns
- when 'year'
- row['year'] = row['tyear']
- when 'month'
- row['month'] = "#{row['tyear']}-#{row['tmonth']}"
- when 'week'
- row['week'] = "#{row['spent_on'].cwyear}-#{row['tweek']}"
- when 'day'
- row['day'] = "#{row['spent_on']}"
- end
- end
-
- min = @hours.collect {|row| row['spent_on']}.min
- @from = min ? min.to_date : Date.today
-
- max = @hours.collect {|row| row['spent_on']}.max
- @to = max ? max.to_date : Date.today
-
- @total_hours = @hours.inject(0) {|s,k| s = s + k['hours'].to_f}
-
- @periods = []
- # Date#at_beginning_of_ not supported in Rails 1.2.x
- date_from = @from.to_time
- # 100 columns max
- while date_from <= @to.to_time && @periods.length < 100
- case @columns
- when 'year'
- @periods << "#{date_from.year}"
- date_from = (date_from + 1.year).at_beginning_of_year
- when 'month'
- @periods << "#{date_from.year}-#{date_from.month}"
- date_from = (date_from + 1.month).at_beginning_of_month
- when 'week'
- @periods << "#{date_from.to_date.cwyear}-#{date_from.to_date.cweek}"
- date_from = (date_from + 7.day).at_beginning_of_week
- when 'day'
- @periods << "#{date_from.to_date}"
- date_from = date_from + 1.day
- end
- end
- end
- end
-
- def load_available_criteria
- @available_criteria = { 'project' => {:sql => "#{TimeEntry.table_name}.project_id",
- :klass => Project,
- :label => :label_project},
- 'status' => {:sql => "#{Issue.table_name}.status_id",
- :klass => IssueStatus,
- :label => :field_status},
- 'version' => {:sql => "#{Issue.table_name}.fixed_version_id",
- :klass => Version,
- :label => :label_version},
- 'category' => {:sql => "#{Issue.table_name}.category_id",
- :klass => IssueCategory,
- :label => :field_category},
- 'user' => {:sql => "#{TimeEntry.table_name}.user_id",
- :klass => User,
- :label => :label_user},
- 'tracker' => {:sql => "#{Issue.table_name}.tracker_id",
- :klass => Tracker,
- :label => :label_tracker},
- 'activity' => {:sql => "#{TimeEntry.table_name}.activity_id",
- :klass => TimeEntryActivity,
- :label => :label_activity},
- 'issue' => {:sql => "#{TimeEntry.table_name}.issue_id",
- :klass => Issue,
- :label => :label_issue}
- }
-
- # Add time entry custom fields
- custom_fields = TimeEntryCustomField.all
- # Add project custom fields
- custom_fields += ProjectCustomField.all
- # Add issue custom fields
- custom_fields += (@project.nil? ? IssueCustomField.for_all : @project.all_issue_custom_fields)
- # Add time entry activity custom fields
- custom_fields += TimeEntryActivityCustomField.all
-
- # Add list and boolean custom fields as available criteria
- custom_fields.select {|cf| %w(list bool).include? cf.field_format }.each do |cf|
- @available_criteria["cf_#{cf.id}"] = {:sql => "#{cf.join_alias}.value",
- :joins => cf.join_for_order_statement,
- :format => cf.field_format,
- :label => cf.name}
- end
-
- @available_criteria
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/hook.rb b/trustie2/lib/redmine/hook.rb
deleted file mode 100644
index e5a2695d1..000000000
--- a/trustie2/lib/redmine/hook.rb
+++ /dev/null
@@ -1,166 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Hook
- @@listener_classes = []
- @@listeners = nil
- @@hook_listeners = {}
-
- class << self
- # Adds a listener class.
- # Automatically called when a class inherits from Redmine::Hook::Listener.
- def add_listener(klass)
- raise "Hooks must include Singleton module." unless klass.included_modules.include?(Singleton)
- @@listener_classes << klass
- clear_listeners_instances
- end
-
- # Returns all the listerners instances.
- def listeners
- @@listeners ||= @@listener_classes.collect {|listener| listener.instance}
- end
-
- # Returns the listeners instances for the given hook.
- def hook_listeners(hook)
- @@hook_listeners[hook] ||= listeners.select {|listener| listener.respond_to?(hook)}
- end
-
- # Clears all the listeners.
- def clear_listeners
- @@listener_classes = []
- clear_listeners_instances
- end
-
- # Clears all the listeners instances.
- def clear_listeners_instances
- @@listeners = nil
- @@hook_listeners = {}
- end
-
- # Calls a hook.
- # Returns the listeners response.
- def call_hook(hook, context={})
- [].tap do |response|
- hls = hook_listeners(hook)
- if hls.any?
- hls.each {|listener| response << listener.send(hook, context)}
- end
- end
- end
- end
-
- # Base class for hook listeners.
- class Listener
- include Singleton
- include Redmine::I18n
-
- # Registers the listener
- def self.inherited(child)
- Redmine::Hook.add_listener(child)
- super
- end
-
- end
-
- # Listener class used for views hooks.
- # Listeners that inherit this class will include various helpers by default.
- class ViewListener < Listener
- include ERB::Util
- include ActionView::Helpers::TagHelper
- include ActionView::Helpers::FormHelper
- include ActionView::Helpers::FormTagHelper
- include ActionView::Helpers::FormOptionsHelper
- include ActionView::Helpers::JavaScriptHelper
- include ActionView::Helpers::NumberHelper
- include ActionView::Helpers::UrlHelper
- include ActionView::Helpers::AssetTagHelper
- include ActionView::Helpers::TextHelper
- include Rails.application.routes.url_helpers
- include ApplicationHelper
-
- # Default to creating links using only the path. Subclasses can
- # change this default as needed
- def self.default_url_options
- {:only_path => true }
- end
-
- # Helper method to directly render a partial using the context:
- #
- # class MyHook < Redmine::Hook::ViewListener
- # render_on :view_issues_show_details_bottom, :partial => "show_more_data"
- # end
- #
- def self.render_on(hook, options={})
- define_method hook do |context|
- if context[:hook_caller].respond_to?(:render)
- context[:hook_caller].send(:render, {:locals => context}.merge(options))
- elsif context[:controller].is_a?(ActionController::Base)
- context[:controller].send(:render_to_string, {:locals => context}.merge(options))
- else
- raise "Cannot render #{self.name} hook from #{context[:hook_caller].class.name}"
- end
- end
- end
-
- def controller
- nil
- end
-
- def config
- ActionController::Base.config
- end
- end
-
- # Helper module included in ApplicationHelper and ActionController so that
- # hooks can be called in views like this:
- #
- # <%= call_hook(:some_hook) %>
- # <%= call_hook(:another_hook, :foo => 'bar') %>
- #
- # Or in controllers like:
- # call_hook(:some_hook)
- # call_hook(:another_hook, :foo => 'bar')
- #
- # Hooks added to views will be concatenated into a string. Hooks added to
- # controllers will return an array of results.
- #
- # Several objects are automatically added to the call context:
- #
- # * project => current project
- # * request => Request instance
- # * controller => current Controller instance
- # * hook_caller => object that called the hook
- #
- module Helper
- def call_hook(hook, context={})
- if is_a?(ActionController::Base)
- default_context = {:controller => self, :project => @project, :request => request, :hook_caller => self}
- Redmine::Hook.call_hook(hook, default_context.merge(context))
- else
- default_context = { :project => @project, :hook_caller => self }
- default_context[:controller] = controller if respond_to?(:controller)
- default_context[:request] = request if respond_to?(:request)
- Redmine::Hook.call_hook(hook, default_context.merge(context)).join(' ').html_safe
- end
- end
- end
- end
-end
-
-ApplicationHelper.send(:include, Redmine::Hook::Helper)
-ActionController::Base.send(:include, Redmine::Hook::Helper)
diff --git a/trustie2/lib/redmine/i18n.rb b/trustie2/lib/redmine/i18n.rb
deleted file mode 100644
index 8d2a0adaa..000000000
--- a/trustie2/lib/redmine/i18n.rb
+++ /dev/null
@@ -1,185 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 I18n
- def self.included(base)
- base.extend Redmine::I18n
- end
-
- def l(*args)
- case args.size
- when 1
- ::I18n.t(*args)
- when 2
- if args.last.is_a?(Hash)
- ::I18n.t(*args)
- elsif args.last.is_a?(String)
- ::I18n.t(args.first, :value => args.last)
- else
- ::I18n.t(args.first, :count => args.last)
- end
- else
- raise "Translation string with multiple values: #{args.first}"
- end
- end
-
- def l_or_humanize(s, options={})
- k = "#{options[:prefix]}#{s}".to_sym
- ::I18n.t(k, :default => s.to_s.humanize)
- end
-
- def l_hours(hours)
- hours = hours.to_f
- l((hours < 2.0 ? :label_f_hour : :label_f_hour_plural), :value => ("%.2f" % hours.to_f))
- end
-
- def ll(lang, str, value=nil)
- ::I18n.t(str.to_s, :value => value, :locale => lang.to_s.gsub(%r{(.+)\-(.+)$}) { "#{$1}-#{$2.upcase}" })
- end
-
- def format_date(date)
- return nil unless date
- options = {}
- options[:format] = Setting.date_format unless Setting.date_format.blank?
- #options[:locale] = User.current.language unless User.current.language.blank?
- ::I18n.l(date.to_date, options)
- end
-
- def format_time(time, include_date = true)
- return nil unless time
- options = {}
- options[:format] = (Setting.time_format.blank? ? :time : Setting.time_format)
- #options[:locale] = User.current.language unless User.current.language.blank?
- time = time.to_time if time.is_a?(String)
- #zone = User.current.time_zone
- zone = 'UTC'
- local = zone ? time.in_time_zone(zone) : (time.utc? ? time.localtime : time)
- (include_date ? "#{format_date(local)} " : "") + ::I18n.l(local, options)
- end
-
- def day_name(day)
- ::I18n.t('date.day_names')[day % 7]
- end
-
- def day_letter(day)
- ::I18n.t('date.abbr_day_names')[day % 7].first
- end
-
- def month_name(month)
- ::I18n.t('date.month_names')[month]
- end
-
- def valid_languages
- ::I18n.available_locales
- end
-
- # Returns an array of languages names and code sorted by names, example:
- # [["Deutsch", "de"], ["English", "en"] ...]
- #
- # The result is cached to prevent from loading all translations files.
- def languages_options
- ActionController::Base.cache_store.fetch "i18n/languages_options" do
- valid_languages.map {|lang| [ll(lang.to_s, :general_lang_name), lang.to_s]}.sort {|x,y| x.first <=> y.first }
- end
- end
-
- def find_language(lang)
- @@languages_lookup = valid_languages.inject({}) {|k, v| k[v.to_s.downcase] = v; k }
- @@languages_lookup[lang.to_s.downcase]
- end
-
- def set_language_if_valid(lang)
- if l = find_language(lang)
- ::I18n.locale = l
- end
- end
-
- def current_language
- ::I18n.locale
- end
-
- # Custom backend based on I18n::Backend::Simple with the following changes:
- # * lazy loading of translation files
- # * available_locales are determined by looking at translation file names
- class Backend
- (class << self; self; end).class_eval { public :include }
-
- module Implementation
- include ::I18n::Backend::Base
-
- # Stores translations for the given locale in memory.
- # This uses a deep merge for the translations hash, so existing
- # translations will be overwritten by new ones only at the deepest
- # level of the hash.
- def store_translations(locale, data, options = {})
- locale = locale.to_sym
- translations[locale] ||= {}
- data = data.deep_symbolize_keys
- translations[locale].deep_merge!(data)
- end
-
- # Get available locales from the translations filenames
- def available_locales
- @available_locales ||= ::I18n.load_path.map {|path| File.basename(path, '.*')}.uniq.sort.map(&:to_sym)
- end
-
- # Clean up translations
- def reload!
- @translations = nil
- @available_locales = nil
- super
- end
-
- protected
-
- def init_translations(locale)
- locale = locale.to_s
- paths = ::I18n.load_path.select {|path| File.basename(path, '.*') == locale}
- load_translations(paths)
- translations[locale] ||= {}
- end
-
- def translations
- @translations ||= {}
- end
-
- # Looks up a translation from the translations hash. Returns nil if
- # eiher key is nil, or locale, scope or key do not exist as a key in the
- # nested translations hash. Splits keys or scopes containing dots
- # into multiple keys, i.e. currency.format is regarded the same as
- # %w(currency format).
- def lookup(locale, key, scope = [], options = {})
- init_translations(locale) unless translations.key?(locale)
- keys = ::I18n.normalize_keys(locale, key, scope, options[:separator])
-
- keys.inject(translations) do |result, _key|
- _key = _key.to_sym
- return nil unless result.is_a?(Hash) && result.has_key?(_key)
- result = result[_key]
- result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol)
- result
- end
- end
- end
-
- include Implementation
- # Adds fallback to default locale for untranslated strings
- include ::I18n::Backend::Fallbacks
- end
- end
-end
diff --git a/trustie2/lib/redmine/imap.rb b/trustie2/lib/redmine/imap.rb
deleted file mode 100644
index 6e15c57e6..000000000
--- a/trustie2/lib/redmine/imap.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'net/imap'
-
-module Redmine
- module IMAP
- class << self
- def check(imap_options={}, options={})
- host = imap_options[:host] || '127.0.0.1'
- port = imap_options[:port] || '143'
- ssl = !imap_options[:ssl].nil?
- folder = imap_options[:folder] || 'INBOX'
-
- imap = Net::IMAP.new(host, port, ssl)
- imap.login(imap_options[:username], imap_options[:password]) unless imap_options[:username].nil?
- imap.select(folder)
- imap.search(['NOT', 'SEEN']).each do |message_id|
- msg = imap.fetch(message_id,'RFC822')[0].attr['RFC822']
- logger.debug "Receiving message #{message_id}" if logger && logger.debug?
- if MailHandler.receive(msg, options)
- logger.debug "Message #{message_id} successfully received" if logger && logger.debug?
- if imap_options[:move_on_success]
- imap.copy(message_id, imap_options[:move_on_success])
- end
- imap.store(message_id, "+FLAGS", [:Seen, :Deleted])
- else
- logger.debug "Message #{message_id} can not be processed" if logger && logger.debug?
- imap.store(message_id, "+FLAGS", [:Seen])
- if imap_options[:move_on_failure]
- imap.copy(message_id, imap_options[:move_on_failure])
- imap.store(message_id, "+FLAGS", [:Deleted])
- end
- end
- end
- imap.expunge
- end
-
- private
-
- def logger
- ::Rails.logger
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/info.rb b/trustie2/lib/redmine/info.rb
deleted file mode 100644
index 63c066da8..000000000
--- a/trustie2/lib/redmine/info.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-module Redmine
- module Info
- class << self
- def app_name; 'Trustie' end
- def url; 'http://forge.trustie.net/' end
- def help_url; 'http://forge.trustie.net/forums' end
- def versioned_name; "#{app_name} #{Redmine::VERSION}" end
-
- def environment
- s = "Environment:\n"
- s << [
- ["Trustie version", Redmine::VERSION],
- ["Ruby version", "#{RUBY_VERSION} (#{RUBY_PLATFORM})"],
- ["Rails version", Rails::VERSION::STRING],
- ["Environment", Rails.env],
- ["Database adapter", ActiveRecord::Base.connection.adapter_name]
- ].map {|info| " %-40s %s" % info}.join("\n")
- s << "\nTrustie plugins:\n"
-
- plugins = Redmine::Plugin.all
- if plugins.any?
- s << plugins.map {|plugin| " %-40s %s" % [plugin.id.to_s, plugin.version.to_s]}.join("\n")
- else
- s << " no plugin installed"
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/menu_manager.rb b/trustie2/lib/redmine/menu_manager.rb
deleted file mode 100644
index e28d46fb8..000000000
--- a/trustie2/lib/redmine/menu_manager.rb
+++ /dev/null
@@ -1,448 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 MenuManager
- class MenuError < StandardError #:nodoc:
- end
-
- module MenuController
- def self.included(base)
- base.extend(ClassMethods)
- end
-
- module ClassMethods
- @@menu_items = Hash.new {|hash, key| hash[key] = {:default => key, :actions => {}}}
- mattr_accessor :menu_items
-
- # Set the menu item name for a controller or specific actions
- # Examples:
- # * menu_item :tickets # => sets the menu name to :tickets for the whole controller
- # * menu_item :tickets, :only => :list # => sets the menu name to :tickets for the 'list' action only
- # * menu_item :tickets, :only => [:list, :show] # => sets the menu name to :tickets for 2 actions only
- #
- # The default menu item name for a controller is controller_name by default
- # Eg. the default menu item name for ProjectsController is :projects
- def menu_item(id, options = {})
- if actions = options[:only]
- actions = [] << actions unless actions.is_a?(Array)
- actions.each {|a| menu_items[controller_name.to_sym][:actions][a.to_sym] = id}
- else
- menu_items[controller_name.to_sym][:default] = id
- end
- end
- end
-
- def menu_items
- self.class.menu_items
- end
-
- # Returns the menu item name according to the current action
- def current_menu_item
- @current_menu_item ||= menu_items[controller_name.to_sym][:actions][action_name.to_sym] ||
- menu_items[controller_name.to_sym][:default]
- end
-
- # Redirects user to the menu item of the given project
- # Returns false if user is not authorized
- def redirect_to_project_menu_item(project, name)
- item = Redmine::MenuManager.items(:project_menu).detect {|i| i.name.to_s == name.to_s}
- if item && User.current.allowed_to?(item.url, project) && (item.condition.nil? || item.condition.call(project))
- redirect_to({item.param => project}.merge(item.url))
- return true
- end
- false
- end
- end
-
- module MenuHelper
- # Returns the current menu item name
- def current_menu_item
- controller.current_menu_item
- end
-
-
- # Renders the application main menu
- def render_main_menu(project)
- render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
- end
-
- def display_main_menu?(project)
- menu_name = project && !project.new_record? ? :project_menu : :application_menu
- Redmine::MenuManager.items(menu_name).children.present?
- end
-
- def render_menu(menu, project=nil)
- links = []
- menu_items_for(menu, project) do |node|
- links << render_menu_node(node, project)
- end
- links.empty? ? nil : content_tag('ul', links.join("\n").html_safe)
- end
-
- def bootstrap_render_menu(menu, project=nil)
- links = []
- menu_items_for(menu, project) do |node|
- links << render_menu_node(node, project)
- end
- s = ''
- # s = ""
- links.empty? ? nil : s.html_safe
- end
-
- def render_menu_node(node, project=nil)
- if node.children.present? || !node.child_menus.nil?
- return render_menu_node_with_children(node, project)
- else
- caption, url, selected = extract_node_details(node, project)
- return content_tag('li',
- render_single_menu_node(node, caption, url, selected))
- end
- end
-
- def render_menu_node_with_children(node, project=nil)
- caption, url, selected = extract_node_details(node, project)
-
- html = [].tap do |html|
- html << ''
- # Parent
- html << render_single_menu_node(node, caption, url, selected)
-
- # Standard children
- standard_children_list = "".html_safe.tap do |child_html|
- node.children.each do |child|
- child_html << render_menu_node(child, project)
- end
- end
-
- html << content_tag(:ul, standard_children_list, :class => 'menu-children') unless standard_children_list.empty?
-
- # Unattached children
- unattached_children_list = render_unattached_children_menu(node, project)
- html << content_tag(:ul, unattached_children_list, :class => 'menu-children unattached') unless unattached_children_list.blank?
-
- html << ' '
- end
- return html.join("\n").html_safe
- end
-
- # Returns a list of unattached children menu items
- def render_unattached_children_menu(node, project)
- return nil unless node.child_menus
-
- "".html_safe.tap do |child_html|
- unattached_children = node.child_menus.call(project)
- # Tree nodes support #each so we need to do object detection
- if unattached_children.is_a? Array
- unattached_children.each do |child|
- child_html << content_tag(:li, render_unattached_menu_item(child, project))
- end
- else
- raise MenuError, ":child_menus must be an array of MenuItems"
- end
- end
- end
-
- def render_single_menu_node(item, caption, url, selected)
- link_to(h(caption), url, item.html_options(:selected => selected))
- end
-
- def render_unattached_menu_item(menu_item, project)
- raise MenuError, ":child_menus must be an array of MenuItems" unless menu_item.is_a? MenuItem
-
- if User.current.allowed_to?(menu_item.url, project)
- link_to(h(menu_item.caption),
- menu_item.url,
- menu_item.html_options)
- end
- end
-
- def menu_items_for(menu, project=nil)
- items = []
- Redmine::MenuManager.items(menu).root.children.each do |node|
- if allowed_node?(node, User.current, project)
- if block_given?
- yield node
- else
- items << node # TODO: not used?
- end
- end
- end
- return block_given? ? nil : items
- end
-
- def extract_node_details(node, project=nil)
- item = node
- url = case item.url
- when Hash
- project.nil? ? item.url : {item.param => project}.merge(item.url)
- when Symbol
- send(item.url)
- else
- item.url
- end
- caption = item.caption(project)
- return [caption, url, (current_menu_item == item.name)]
- end
-
- # Checks if a user is allowed to access the menu item by:
- #
- # * Checking the url target (project only)
- # * Checking the conditions of the item
- def allowed_node?(node, user, project)
- if project && user && !user.allowed_to?(node.url, project)
- return false
- end
- if node.condition && !node.condition.call(project)
- # Condition that doesn't pass
- return false
- end
- return true
- end
- end
-
- class << self
- def map(menu_name)
- @items ||= {}
- mapper = Mapper.new(menu_name.to_sym, @items)
- if block_given?
- yield mapper
- else
- mapper
- end
- end
-
- def items(menu_name)
- @items[menu_name.to_sym] || MenuNode.new(:root, {})
- end
- end
-
- class Mapper
- def initialize(menu, items)
- items[menu] ||= MenuNode.new(:root, {})
- @menu = menu
- @menu_items = items[menu]
- end
-
- # Adds an item at the end of the menu. Available options:
- # * param: the parameter name that is used for the project id (default is :id)
- # * if: a Proc that is called before rendering the item, the item is displayed only if it returns true
- # * caption that can be:
- # * a localized string Symbol
- # * a String
- # * a Proc that can take the project as argument
- # * before, after: specify where the menu item should be inserted (eg. :after => :activity)
- # * parent: menu item will be added as a child of another named menu (eg. :parent => :issues)
- # * children: a Proc that is called before rendering the item. The Proc should return an array of MenuItems, which will be added as children to this item.
- # eg. :children => Proc.new {|project| [Redmine::MenuManager::MenuItem.new(...)] }
- # * last: menu item will stay at the end (eg. :last => true)
- # * html_options: a hash of html options that are passed to link_to
- def push(name, url, options={})
- options = options.dup
-
- if options[:parent]
- subtree = self.find(options[:parent])
- if subtree
- target_root = subtree
- else
- target_root = @menu_items.root
- end
-
- else
- target_root = @menu_items.root
- end
-
- # menu item position
- if first = options.delete(:first)
- target_root.prepend(MenuItem.new(name, url, options))
- elsif before = options.delete(:before)
-
- if exists?(before)
- target_root.add_at(MenuItem.new(name, url, options), position_of(before))
- else
- target_root.add(MenuItem.new(name, url, options))
- end
-
- elsif after = options.delete(:after)
-
- if exists?(after)
- target_root.add_at(MenuItem.new(name, url, options), position_of(after) + 1)
- else
- target_root.add(MenuItem.new(name, url, options))
- end
-
- elsif options[:last] # don't delete, needs to be stored
- target_root.add_last(MenuItem.new(name, url, options))
- else
- target_root.add(MenuItem.new(name, url, options))
- end
- end
-
- # Removes a menu item
- def delete(name)
- if found = self.find(name)
- @menu_items.remove!(found)
- end
- end
-
- # Checks if a menu item exists
- def exists?(name)
- @menu_items.any? {|node| node.name == name}
- end
-
- def find(name)
- @menu_items.find {|node| node.name == name}
- end
-
- def position_of(name)
- @menu_items.each do |node|
- if node.name == name
- return node.position
- end
- end
- end
- end
-
- class MenuNode
- include Enumerable
- attr_accessor :parent
- attr_reader :last_items_count, :name
-
- def initialize(name, content = nil)
- @name = name
- @children = []
- @last_items_count = 0
- end
-
- def children
- if block_given?
- @children.each {|child| yield child}
- else
- @children
- end
- end
-
- # Returns the number of descendants + 1
- def size
- @children.inject(1) {|sum, node| sum + node.size}
- end
-
- def each &block
- yield self
- children { |child| child.each(&block) }
- end
-
- # Adds a child at first position
- def prepend(child)
- add_at(child, 0)
- end
-
- # Adds a child at given position
- def add_at(child, position)
- raise "Child already added" if find {|node| node.name == child.name}
-
- @children = @children.insert(position, child)
- child.parent = self
- child
- end
-
- # Adds a child as last child
- def add_last(child)
- add_at(child, -1)
- @last_items_count += 1
- child
- end
-
- # Adds a child
- def add(child)
- position = @children.size - @last_items_count
- add_at(child, position)
- end
- alias :<< :add
-
- # Removes a child
- def remove!(child)
- @children.delete(child)
- @last_items_count -= +1 if child && child.last
- child.parent = nil
- child
- end
-
- # Returns the position for this node in it's parent
- def position
- self.parent.children.index(self)
- end
-
- # Returns the root for this node
- def root
- root = self
- root = root.parent while root.parent
- root
- end
- end
-
- class MenuItem < MenuNode
- include Redmine::I18n
- attr_reader :name, :url, :param, :condition, :parent, :child_menus, :last
-
- def initialize(name, url, options)
- raise ArgumentError, "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
- raise ArgumentError, "Invalid option :html for menu item '#{name}'" if options[:html] && !options[:html].is_a?(Hash)
- raise ArgumentError, "Cannot set the :parent to be the same as this item" if options[:parent] == name.to_sym
- raise ArgumentError, "Invalid option :children for menu item '#{name}'" if options[:children] && !options[:children].respond_to?(:call)
- @name = name
- @url = url
- @condition = options[:if]
- @param = options[:param] || :id
- @caption = options[:caption]
- @html_options = options[:html] || {}
- # Adds a unique class to each menu item based on its name
- @html_options[:class] = [@html_options[:class], @name.to_s.dasherize].compact.join(' ')
- @parent = options[:parent]
- @child_menus = options[:children]
- @last = options[:last] || false
- super @name.to_sym
- end
-
- def caption(project=nil)
- if @caption.is_a?(Proc)
- c = @caption.call(project).to_s
- c = @name.to_s.humanize if c.blank?
- c
- else
- if @caption.nil?
- l_or_humanize(name, :prefix => 'label_')
- else
- @caption.is_a?(Symbol) ? l(@caption) : @caption
- end
- end
- end
-
- def html_options(options={})
- if options[:selected]
- o = @html_options.dup
- o[:class] += ' selected'
- o
- else
- @html_options
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/mime_type.rb b/trustie2/lib/redmine/mime_type.rb
deleted file mode 100644
index d902c995c..000000000
--- a/trustie2/lib/redmine/mime_type.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 MimeType
-
- MIME_TYPES = {
- 'text/plain' => 'txt,tpl,properties,patch,diff,ini,readme,install,upgrade',
- 'text/css' => 'css',
- 'text/html' => 'html,htm,xhtml',
- 'text/jsp' => 'jsp',
- 'text/x-c' => 'c,cpp,cc,h,hh',
- 'text/x-csharp' => 'cs',
- 'text/x-java' => 'java',
- 'text/x-html-template' => 'rhtml',
- 'text/x-perl' => 'pl,pm',
- 'text/x-php' => 'php,php3,php4,php5',
- 'text/x-python' => 'py',
- 'text/x-ruby' => 'rb,rbw,ruby,rake,erb',
- 'text/x-csh' => 'csh',
- 'text/x-sh' => 'sh',
- 'text/xml' => 'xml,xsd,mxml',
- 'text/yaml' => 'yml,yaml',
- 'text/csv' => 'csv',
- 'text/x-po' => 'po',
- 'image/gif' => 'gif',
- 'image/jpeg' => 'jpg,jpeg,jpe',
- 'image/png' => 'png',
- 'image/tiff' => 'tiff,tif',
- 'image/x-ms-bmp' => 'bmp',
- 'image/x-xpixmap' => 'xpm',
- 'image/svg+xml'=> 'svg',
- 'application/javascript' => 'js',
- 'application/pdf' => 'pdf',
- 'application/rtf' => 'rtf',
- 'application/msword' => 'doc',
- 'application/vnd.ms-excel' => 'xls',
- 'application/vnd.ms-powerpoint' => 'ppt,pps',
- 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
- 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
- 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
- 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
- 'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
- 'application/vnd.oasis.opendocument.text' => 'odt',
- 'application/vnd.oasis.opendocument.presentation' => 'odp',
- 'application/x-7z-compressed' => '7z',
- 'application/x-rar-compressed' => 'rar',
- 'application/x-tar' => 'tar',
- 'application/zip' => 'zip',
- 'application/x-gzip' => 'gz',
- }.freeze
-
- EXTENSIONS = MIME_TYPES.inject({}) do |map, (type, exts)|
- exts.split(',').each {|ext| map[ext.strip] = type}
- map
- end
-
- # returns mime type for name or nil if unknown
- def self.of(name)
- return nil unless name
- m = name.to_s.match(/(^|\.)([^\.]+)$/)
- EXTENSIONS[m[2].downcase] if m
- end
-
- # Returns the css class associated to
- # the mime type of name
- def self.css_class_of(name)
- mime = of(name)
- mime && mime.gsub('/', '-')
- end
-
- def self.main_mimetype_of(name)
- mimetype = of(name)
- mimetype.split('/').first if mimetype
- end
-
- # return true if mime-type for name is type/*
- # otherwise false
- def self.is_type?(type, name)
- main_mimetype = main_mimetype_of(name)
- type.to_s == main_mimetype
- end
- end
-end
diff --git a/trustie2/lib/redmine/notifiable.rb b/trustie2/lib/redmine/notifiable.rb
deleted file mode 100644
index 88ca9d776..000000000
--- a/trustie2/lib/redmine/notifiable.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-module Redmine
- class Notifiable < Struct.new(:name, :parent)
-
- def to_s
- name
- end
-
- # TODO: Plugin API for adding a new notification?
- def self.all
- notifications = []
- notifications << Notifiable.new('issue_added')
- notifications << Notifiable.new('issue_updated')
- notifications << Notifiable.new('issue_note_added', 'issue_updated')
- notifications << Notifiable.new('issue_status_updated', 'issue_updated')
- notifications << Notifiable.new('issue_priority_updated', 'issue_updated')
- notifications << Notifiable.new('news_added')
- notifications << Notifiable.new('news_comment_added')
- notifications << Notifiable.new('document_added')
- notifications << Notifiable.new('file_added')
- notifications << Notifiable.new('message_posted')
- notifications << Notifiable.new('wiki_content_added')
- notifications << Notifiable.new('wiki_content_updated')
- notifications
- end
- end
-end
diff --git a/trustie2/lib/redmine/pagination.rb b/trustie2/lib/redmine/pagination.rb
deleted file mode 100644
index fef8bfa23..000000000
--- a/trustie2/lib/redmine/pagination.rb
+++ /dev/null
@@ -1,311 +0,0 @@
-# encoding: utf-8
-#
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Pagination
- class Paginator
- attr_reader :item_count, :per_page, :page, :page_param
- def initialize(*args)
- if args.first.is_a?(ActionController::Base)
- args.shift
- ActiveSupport::Deprecation.warn "Paginator no longer takes a controller instance as the first argument. Remove it from #new arguments."
- end
- item_count, per_page, page, page_param = *args
-
- @item_count = item_count
- @per_page = per_page
- page = (page || 1).to_i
- if page < 1
- page = 1
- end
- @page = page
- @page_param = page_param || :page
- end
-
- def offset
- (page - 1) * per_page
- end
-
- ## fq
- def reverse_offset
- offset = @item_count-@per_page*page
- if offset < 0
- offset = 0
- end
- offset
- end
- ## end
-
-
- def first_page
- if item_count > 0
- 1
- end
- end
-
- def previous_page
- if page > 1
- page - 1
- end
- end
-
- def next_page
- if last_item < item_count
- page + 1
- end
- end
-
- def last_page
- if item_count > 0
- (item_count - 1) / per_page + 1
- end
- end
-
- def first_item
- item_count == 0 ? 0 : (offset + 1)
- end
-
- def last_item
- l = first_item + per_page - 1
- l > item_count ? item_count : l
- end
-
- def linked_pages
- pages = []
- if item_count > 0
- pages += [first_page, page, last_page]
- pages += ((page-2)..(page+2)).to_a.select {|p| p > first_page && p < last_page}
- end
- pages = pages.compact.uniq.sort
- if pages.size > 1
- pages
- else
- []
- end
- end
-
- def items_per_page
- ActiveSupport::Deprecation.warn "Paginator#items_per_page will be removed. Use #per_page instead."
- per_page
- end
-
- def current
- ActiveSupport::Deprecation.warn "Paginator#current will be removed. Use .offset instead of .current.offset."
- self
- end
- end
-
- # Paginates the given scope or model. Returns a Paginator instance and
- # the collection of objects for the current page.
- #
- # Options:
- # :parameter name of the page parameter
- #
- # Examples:
- # @user_pages, @users = paginate User.where(:status => 1)
- #
- def paginate(scope, options={})
- options = options.dup
- finder_options = options.extract!(
- :conditions,
- :order,
- :joins,
- :include,
- :select
- )
- if scope.is_a?(Symbol) || finder_options.values.compact.any?
- return deprecated_paginate(scope, finder_options, options)
- end
-
- paginator = paginator(scope.count, options)
- collection = scope.limit(paginator.per_page).offset(paginator.offset).to_a
-
- return paginator, collection
- end
-
- def deprecated_paginate(arg, finder_options, options={})
- ActiveSupport::Deprecation.warn "#paginate with a Symbol and/or find options is depreceted and will be removed. Use a scope instead."
- klass = arg.is_a?(Symbol) ? arg.to_s.classify.constantize : arg
- scope = klass.scoped(finder_options)
- paginate(scope, options)
- end
-
- def paginator(item_count, options={})
- options.assert_valid_keys :parameter, :per_page
-
- page_param = options[:parameter] || :page
- page = (params[page_param] || 1).to_i
- per_page = options[:per_page] || per_page_option
- Paginator.new(item_count, per_page, page, page_param)
- end
-
- module Helper
- include Redmine::I18n
- # Renders the pagination links for the given paginator.
- #
- # Options:
- # :per_page_links if set to false, the "Per page" links are not rendered
- #
- def pagination_links_full(*args)
- pagination_links_each(*args) do |text, parameters, options|
- if block_given?
- yield text, parameters, options
- else
- link_to text, params.merge(parameters), options
- end
- end
- end
-
- # Yields the given block with the text and parameters
- # for each pagination link and returns a string that represents the links
- # def pagination_links_each(paginator, count=nil, options={}, &block)
- # options.assert_valid_keys :per_page_links
- #
- # per_page_links = options.delete(:per_page_links)
- # per_page_links = false if count.nil?
- # page_param = paginator.page_param
- #
- # html = ''
- # if paginator.previous_page
- # # \xc2\xab(utf-8) = «
- # text = "\xc2\xab " + l(:label_previous)
- # html << yield(text, {page_param => paginator.previous_page}, :class => 'previous') + ' '
- # end
- #
- # previous = nil
- # paginator.linked_pages.each do |page|
- # if previous && previous != page - 1
- # html << content_tag('span', '...', :class => 'spacer') + ' '
- # end
- # if page == paginator.page
- # html << content_tag('span', page.to_s, :class => 'current page')
- # else
- # html << yield(page.to_s, {page_param => page}, :class => 'page')
- # end
- # html << ' '
- # previous = page
- # end
- #
- # if paginator.next_page
- # # \xc2\xbb(utf-8) = »
- # text = l(:label_next) + " \xc2\xbb"
- # html << yield(text, {page_param => paginator.next_page}, :class => 'next') + ' '
- # end
- #
- # html << content_tag('span', "(#{paginator.first_item}-#{paginator.last_item}/#{paginator.item_count})", :class => 'items') + ' '
- #
- # if per_page_links != false && links = per_page_links(paginator, &block)
- # html << content_tag('span', links.to_s, :class => 'per-page')
- # end
- #
- # html.html_safe
- # end
- #Added by Nie guanghui
- #Designed for pagination.
- def pagination_links_each(paginator, count=nil, options={}, &block)
- options.assert_valid_keys :per_page_links
-
- per_page_links = options.delete(:per_page_links)
- per_page_links = false if count.nil?
- page_param = paginator.page_param
-
- html = ''
- if paginator.previous_page
- # \xc2\xab(utf-8) = «
- text = "\xc2\xab " + l(:label_previous)
- html << '' << yield(text, {page_param => paginator.previous_page}, :class => 'previous') << ' ' + ' '
- end
- unless paginator.previous_page
- if paginator.next_page
- text = "\xc2\xab " + l(:label_previous)
- html << '' << yield(text, {page_param => paginator.previous_page}, :class => 'previous') << ' ' + ' '
- end
- end
-
- previous = nil
- paginator.linked_pages.each do |page|
- if previous && previous != page - 1
- html << '' << content_tag('span', '...', :class => 'spacer') << ' ' + ' '
- end
- if page == paginator.page
- html << '' << content_tag('span', page.to_s, :class => 'current-page') << ' '
- else
- html << '' << yield(page.to_s, {page_param => page}, :class => 'page') << ' '
- end
- html << ' '
- previous = page
- end
-
- if paginator.next_page
- # \xc2\xbb(utf-8) = »
- text = l(:label_next) + " \xc2\xbb"
- html << '' << yield(text, {page_param => paginator.next_page}, :class => 'next') << ' ' + ' '
- end
-
- unless paginator.next_page
- if paginator.previous_page
- # \xc2\xbb(utf-8) = »
- text = l(:label_front) + " \xc2\xbb"
- html << "" << yield(text, {page_param => paginator.next_page}, :class => 'next') << " " + ' '
- end
- end
-
- # html << content_tag('span', "(#{paginator.first_item}-#{paginator.last_item}/#{paginator.item_count})", :class => 'items') + ' '
- #
- # if per_page_links != false && links = per_page_links(paginator, &block)
- # html << content_tag('span', links.to_s, :class => 'per-page')
- # end
-
- html.html_safe
- end
-
- # Renders the "Per page" links.
- def per_page_links(paginator, &block)
- values = per_page_options(paginator.per_page, paginator.item_count)
- if values.any?
- links = values.collect do |n|
- if n == paginator.per_page
- content_tag('span', n.to_s)
- else
- yield(n, :per_page => n, paginator.page_param => nil)
- end
- end
- l(:label_display_per_page, links.join(', ')).html_safe
- end
- end
-
- def per_page_options(selected=nil, item_count=nil)
- options = Setting.per_page_options_array
- if item_count && options.any?
- if item_count > options.first
- max = options.detect {|value| value >= item_count} || item_count
- else
- max = item_count
- end
- options = options.select {|value| value <= max || value == selected}
- end
- if options.empty? || (options.size == 1 && options.first == selected)
- []
- else
- options
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/platform.rb b/trustie2/lib/redmine/platform.rb
deleted file mode 100644
index e06ebeeed..000000000
--- a/trustie2/lib/redmine/platform.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Platform
- class << self
- def mswin?
- (RUBY_PLATFORM =~ /(:?mswin|mingw)/) ||
- (RUBY_PLATFORM == 'java' && (ENV['OS'] || ENV['os']) =~ /windows/i)
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/plugin.rb b/trustie2/lib/redmine/plugin.rb
deleted file mode 100644
index 30c182d17..000000000
--- a/trustie2/lib/redmine/plugin.rb
+++ /dev/null
@@ -1,476 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 #:nodoc:
-
- class PluginNotFound < StandardError; end
- class PluginRequirementError < StandardError; end
-
- # Base class for Redmine plugins.
- # Plugins are registered using the register class method that acts as the public constructor.
- #
- # Redmine::Plugin.register :example do
- # name 'Example plugin'
- # author 'John Smith'
- # description 'This is an example plugin for Redmine'
- # version '0.0.1'
- # settings :default => {'foo'=>'bar'}, :partial => 'settings/settings'
- # end
- #
- # === Plugin attributes
- #
- # +settings+ is an optional attribute that let the plugin be configurable.
- # It must be a hash with the following keys:
- # * :default: default value for the plugin settings
- # * :partial: path of the configuration partial view, relative to the plugin app/views directory
- # Example:
- # settings :default => {'foo'=>'bar'}, :partial => 'settings/settings'
- # In this example, the settings partial will be found here in the plugin directory: app/views/settings/_settings.rhtml.
- #
- # When rendered, the plugin settings value is available as the local variable +settings+
- class Plugin
- cattr_accessor :directory
- self.directory = File.join(Rails.root, 'plugins')
-
- cattr_accessor :public_directory
- self.public_directory = File.join(Rails.root, 'public', 'plugin_assets')
-
- @registered_plugins = {}
- class << self
- attr_reader :registered_plugins
- private :new
-
- def def_field(*names)
- class_eval do
- names.each do |name|
- define_method(name) do |*args|
- args.empty? ? instance_variable_get("@#{name}") : instance_variable_set("@#{name}", *args)
- end
- end
- end
- end
- end
- def_field :name, :description, :url, :author, :author_url, :version, :settings
- attr_reader :id
-
- # Plugin constructor
- def self.register(id, &block)
- p = new(id)
- p.instance_eval(&block)
- # Set a default name if it was not provided during registration
- p.name(id.to_s.humanize) if p.name.nil?
-
- # Adds plugin locales if any
- # YAML translation files should be found under /config/locales/
- ::I18n.load_path += Dir.glob(File.join(p.directory, 'config', 'locales', '*.yml'))
-
- # Prepends the app/views directory of the plugin to the view path
- view_path = File.join(p.directory, 'app', 'views')
- if File.directory?(view_path)
- ActionController::Base.prepend_view_path(view_path)
- ActionMailer::Base.prepend_view_path(view_path)
- end
-
- # Adds the app/{controllers,helpers,models} directories of the plugin to the autoload path
- Dir.glob File.expand_path(File.join(p.directory, 'app', '{controllers,helpers,models}')) do |dir|
- ActiveSupport::Dependencies.autoload_paths += [dir]
- end
-
- registered_plugins[id] = p
- end
-
- # Returns an array of all registered plugins
- def self.all
- registered_plugins.values.sort
- end
-
- # Finds a plugin by its id
- # Returns a PluginNotFound exception if the plugin doesn't exist
- def self.find(id)
- registered_plugins[id.to_sym] || raise(PluginNotFound)
- end
-
- # Clears the registered plugins hash
- # It doesn't unload installed plugins
- def self.clear
- @registered_plugins = {}
- end
-
- # Checks if a plugin is installed
- #
- # @param [String] id name of the plugin
- def self.installed?(id)
- registered_plugins[id.to_sym].present?
- end
-
- def self.load
- Dir.glob(File.join(self.directory, '*')).sort.each do |directory|
- if File.directory?(directory)
- lib = File.join(directory, "lib")
- if File.directory?(lib)
- $:.unshift lib
- ActiveSupport::Dependencies.autoload_paths += [lib]
- end
- initializer = File.join(directory, "init.rb")
- if File.file?(initializer)
- require initializer
- end
- end
- end
- end
-
- def initialize(id)
- @id = id.to_sym
- end
-
- def directory
- File.join(self.class.directory, id.to_s)
- end
-
- def public_directory
- File.join(self.class.public_directory, id.to_s)
- end
-
- def to_param
- id
- end
-
- def assets_directory
- File.join(directory, 'assets')
- end
-
- def <=>(plugin)
- self.id.to_s <=> plugin.id.to_s
- end
-
- # Sets a requirement on Redmine version
- # Raises a PluginRequirementError exception if the requirement is not met
- #
- # Examples
- # # Requires Redmine 0.7.3 or higher
- # requires_redmine :version_or_higher => '0.7.3'
- # requires_redmine '0.7.3'
- #
- # # Requires Redmine 0.7.x or higher
- # requires_redmine '0.7'
- #
- # # Requires a specific Redmine version
- # requires_redmine :version => '0.7.3' # 0.7.3 only
- # requires_redmine :version => '0.7' # 0.7.x
- # requires_redmine :version => ['0.7.3', '0.8.0'] # 0.7.3 or 0.8.0
- #
- # # Requires a Redmine version within a range
- # requires_redmine :version => '0.7.3'..'0.9.1' # >= 0.7.3 and <= 0.9.1
- # requires_redmine :version => '0.7'..'0.9' # >= 0.7.x and <= 0.9.x
- def requires_redmine(arg)
- arg = { :version_or_higher => arg } unless arg.is_a?(Hash)
- arg.assert_valid_keys(:version, :version_or_higher)
-
- current = Redmine::VERSION.to_a
- arg.each do |k, req|
- case k
- when :version_or_higher
- raise ArgumentError.new(":version_or_higher accepts a version string only") unless req.is_a?(String)
- unless compare_versions(req, current) <= 0
- raise PluginRequirementError.new("#{id} plugin requires Redmine #{req} or higher but current is #{current.join('.')}")
- end
- when :version
- req = [req] if req.is_a?(String)
- if req.is_a?(Array)
- unless req.detect {|ver| compare_versions(ver, current) == 0}
- raise PluginRequirementError.new("#{id} plugin requires one the following Redmine versions: #{req.join(', ')} but current is #{current.join('.')}")
- end
- elsif req.is_a?(Range)
- unless compare_versions(req.first, current) <= 0 && compare_versions(req.last, current) >= 0
- raise PluginRequirementError.new("#{id} plugin requires a Redmine version between #{req.first} and #{req.last} but current is #{current.join('.')}")
- end
- else
- raise ArgumentError.new(":version option accepts a version string, an array or a range of versions")
- end
- end
- end
- true
- end
-
- def compare_versions(requirement, current)
- requirement = requirement.split('.').collect(&:to_i)
- requirement <=> current.slice(0, requirement.size)
- end
- private :compare_versions
-
- # Sets a requirement on a Redmine plugin version
- # Raises a PluginRequirementError exception if the requirement is not met
- #
- # Examples
- # # Requires a plugin named :foo version 0.7.3 or higher
- # requires_redmine_plugin :foo, :version_or_higher => '0.7.3'
- # requires_redmine_plugin :foo, '0.7.3'
- #
- # # Requires a specific version of a Redmine plugin
- # requires_redmine_plugin :foo, :version => '0.7.3' # 0.7.3 only
- # requires_redmine_plugin :foo, :version => ['0.7.3', '0.8.0'] # 0.7.3 or 0.8.0
- def requires_redmine_plugin(plugin_name, arg)
- arg = { :version_or_higher => arg } unless arg.is_a?(Hash)
- arg.assert_valid_keys(:version, :version_or_higher)
-
- plugin = Plugin.find(plugin_name)
- current = plugin.version.split('.').collect(&:to_i)
-
- arg.each do |k, v|
- v = [] << v unless v.is_a?(Array)
- versions = v.collect {|s| s.split('.').collect(&:to_i)}
- case k
- when :version_or_higher
- raise ArgumentError.new("wrong number of versions (#{versions.size} for 1)") unless versions.size == 1
- unless (current <=> versions.first) >= 0
- raise PluginRequirementError.new("#{id} plugin requires the #{plugin_name} plugin #{v} or higher but current is #{current.join('.')}")
- end
- when :version
- unless versions.include?(current.slice(0,3))
- raise PluginRequirementError.new("#{id} plugin requires one the following versions of #{plugin_name}: #{v.join(', ')} but current is #{current.join('.')}")
- end
- end
- end
- true
- end
-
- # Adds an item to the given +menu+.
- # The +id+ parameter (equals to the project id) is automatically added to the url.
- # menu :project_menu, :plugin_example, { :controller => 'example', :action => 'say_hello' }, :caption => 'Sample'
- #
- # +name+ parameter can be: :top_menu, :account_menu, :application_menu or :project_menu
- #
- def menu(menu, item, url, options={})
- Redmine::MenuManager.map(menu).push(item, url, options)
- end
- alias :add_menu_item :menu
-
- # Removes +item+ from the given +menu+.
- def delete_menu_item(menu, item)
- Redmine::MenuManager.map(menu).delete(item)
- end
-
- # Defines a permission called +name+ for the given +actions+.
- #
- # The +actions+ argument is a hash with controllers as keys and actions as values (a single value or an array):
- # permission :destroy_contacts, { :contacts => :destroy }
- # permission :view_contacts, { :contacts => [:index, :show] }
- #
- # The +options+ argument is a hash that accept the following keys:
- # * :public => the permission is public if set to true (implicitly given to any user)
- # * :require => can be set to one of the following values to restrict users the permission can be given to: :loggedin, :member
- # * :read => set it to true so that the permission is still granted on closed projects
- #
- # Examples
- # # A permission that is implicitly given to any user
- # # This permission won't appear on the Roles & Permissions setup screen
- # permission :say_hello, { :example => :say_hello }, :public => true, :read => true
- #
- # # A permission that can be given to any user
- # permission :say_hello, { :example => :say_hello }
- #
- # # A permission that can be given to registered users only
- # permission :say_hello, { :example => :say_hello }, :require => :loggedin
- #
- # # A permission that can be given to project members only
- # permission :say_hello, { :example => :say_hello }, :require => :member
- def permission(name, actions, options = {})
- if @project_module
- Redmine::AccessControl.map {|map| map.project_module(@project_module) {|map|map.permission(name, actions, options)}}
- else
- Redmine::AccessControl.map {|map| map.permission(name, actions, options)}
- end
- end
-
- # Defines a project module, that can be enabled/disabled for each project.
- # Permissions defined inside +block+ will be bind to the module.
- #
- # project_module :things do
- # permission :view_contacts, { :contacts => [:list, :show] }, :public => true
- # permission :destroy_contacts, { :contacts => :destroy }
- # end
- def project_module(name, &block)
- @project_module = name
- self.instance_eval(&block)
- @project_module = nil
- end
-
- # Registers an activity provider.
- #
- # Options:
- # * :class_name - one or more model(s) that provide these events (inferred from event_type by default)
- # * :default - setting this option to false will make the events not displayed by default
- #
- # A model can provide several activity event types.
- #
- # Examples:
- # register :news
- # register :scrums, :class_name => 'Meeting'
- # register :issues, :class_name => ['Issue', 'Journal']
- #
- # Retrieving events:
- # Associated model(s) must implement the find_events class method.
- # ActiveRecord models can use acts_as_activity_provider as a way to implement this class method.
- #
- # The following call should return all the scrum events visible by current user that occured in the 5 last days:
- # Meeting.find_events('scrums', User.current, 5.days.ago, Date.today)
- # Meeting.find_events('scrums', User.current, 5.days.ago, Date.today, :project => foo) # events for project foo only
- #
- # Note that :view_scrums permission is required to view these events in the activity view.
- def activity_provider(*args)
- Redmine::Activity.register(*args)
- end
-
- # Registers a wiki formatter.
- #
- # Parameters:
- # * +name+ - human-readable name
- # * +formatter+ - formatter class, which should have an instance method +to_html+
- # * +helper+ - helper module, which will be included by wiki pages
- def wiki_format_provider(name, formatter, helper)
- Redmine::WikiFormatting.register(name, formatter, helper)
- end
-
- # Returns +true+ if the plugin can be configured.
- def configurable?
- settings && settings.is_a?(Hash) && !settings[:partial].blank?
- end
-
- def mirror_assets
- source = assets_directory
- destination = public_directory
- return unless File.directory?(source)
-
- source_files = Dir[source + "/**/*"]
- source_dirs = source_files.select { |d| File.directory?(d) }
- source_files -= source_dirs
-
- unless source_files.empty?
- base_target_dir = File.join(destination, File.dirname(source_files.first).gsub(source, ''))
- begin
- FileUtils.mkdir_p(base_target_dir)
- rescue Exception => e
- raise "Could not create directory #{base_target_dir}: " + e.message
- end
- end
-
- source_dirs.each do |dir|
- # strip down these paths so we have simple, relative paths we can
- # add to the destination
- target_dir = File.join(destination, dir.gsub(source, ''))
- begin
- FileUtils.mkdir_p(target_dir)
- rescue Exception => e
- raise "Could not create directory #{target_dir}: " + e.message
- end
- end
-
- source_files.each do |file|
- begin
- target = File.join(destination, file.gsub(source, ''))
- unless File.exist?(target) && FileUtils.identical?(file, target)
- FileUtils.cp(file, target)
- end
- rescue Exception => e
- raise "Could not copy #{file} to #{target}: " + e.message
- end
- end
- end
-
- # Mirrors assets from one or all plugins to public/plugin_assets
- def self.mirror_assets(name=nil)
- if name.present?
- find(name).mirror_assets
- else
- all.each do |plugin|
- plugin.mirror_assets
- end
- end
- end
-
- # The directory containing this plugin's migrations (plugin/db/migrate)
- def migration_directory
- File.join(Rails.root, 'plugins', id.to_s, 'db', 'migrate')
- end
-
- # Returns the version number of the latest migration for this plugin. Returns
- # nil if this plugin has no migrations.
- def latest_migration
- migrations.last
- end
-
- # Returns the version numbers of all migrations for this plugin.
- def migrations
- migrations = Dir[migration_directory+"/*.rb"]
- migrations.map { |p| File.basename(p).match(/0*(\d+)\_/)[1].to_i }.sort
- end
-
- # Migrate this plugin to the given version
- def migrate(version = nil)
- puts "Migrating #{id} (#{name})..."
- Redmine::Plugin::Migrator.migrate_plugin(self, version)
- end
-
- # Migrates all plugins or a single plugin to a given version
- # Exemples:
- # Plugin.migrate
- # Plugin.migrate('sample_plugin')
- # Plugin.migrate('sample_plugin', 1)
- #
- def self.migrate(name=nil, version=nil)
- if name.present?
- find(name).migrate(version)
- else
- all.each do |plugin|
- plugin.migrate
- end
- end
- end
-
- class Migrator < ActiveRecord::Migrator
- # We need to be able to set the 'current' plugin being migrated.
- cattr_accessor :current_plugin
-
- class << self
- # Runs the migrations from a plugin, up (or down) to the version given
- def migrate_plugin(plugin, version)
- self.current_plugin = plugin
- return if current_version(plugin) == version
- migrate(plugin.migration_directory, version)
- end
-
- def current_version(plugin=current_plugin)
- # Delete migrations that don't match .. to_i will work because the number comes first
- ::ActiveRecord::Base.connection.select_values(
- "SELECT version FROM #{schema_migrations_table_name}"
- ).delete_if{ |v| v.match(/-#{plugin.id}/) == nil }.map(&:to_i).max || 0
- end
- end
-
- def migrated
- sm_table = self.class.schema_migrations_table_name
- ::ActiveRecord::Base.connection.select_values(
- "SELECT version FROM #{sm_table}"
- ).delete_if{ |v| v.match(/-#{current_plugin.id}/) == nil }.map(&:to_i).sort
- end
-
- def record_version_state_after_migrating(version)
- super(version.to_s + "-" + current_plugin.id.to_s)
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/pop3.rb b/trustie2/lib/redmine/pop3.rb
deleted file mode 100644
index 275e688de..000000000
--- a/trustie2/lib/redmine/pop3.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'net/pop'
-
-module Redmine
- module POP3
- class << self
- def check(pop_options={}, options={})
- host = pop_options[:host] || '127.0.0.1'
- port = pop_options[:port] || '110'
- apop = (pop_options[:apop].to_s == '1')
- delete_unprocessed = (pop_options[:delete_unprocessed].to_s == '1')
-
- pop = Net::POP3.APOP(apop).new(host,port)
- logger.debug "Connecting to #{host}..." if logger && logger.debug?
- pop.start(pop_options[:username], pop_options[:password]) do |pop_session|
- if pop_session.mails.empty?
- logger.debug "No email to process" if logger && logger.debug?
- else
- logger.debug "#{pop_session.mails.size} email(s) to process..." if logger && logger.debug?
- pop_session.each_mail do |msg|
- message = msg.pop
- message_id = (message =~ /^Message-I[dD]: (.*)/ ? $1 : '').strip
- if MailHandler.receive(message, options)
- msg.delete
- logger.debug "--> Message #{message_id} processed and deleted from the server" if logger && logger.debug?
- else
- if delete_unprocessed
- msg.delete
- logger.debug "--> Message #{message_id} NOT processed and deleted from the server" if logger && logger.debug?
- else
- logger.debug "--> Message #{message_id} NOT processed and left on the server" if logger && logger.debug?
- end
- end
- end
- end
- end
- end
-
- private
-
- def logger
- ::Rails.logger
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/safe_attributes.rb b/trustie2/lib/redmine/safe_attributes.rb
deleted file mode 100644
index c8d5852bc..000000000
--- a/trustie2/lib/redmine/safe_attributes.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 SafeAttributes
- def self.included(base)
- base.extend(ClassMethods)
- end
-
- module ClassMethods
- # Declares safe attributes
- # An optional Proc can be given for conditional inclusion
- #
- # Example:
- # safe_attributes 'title', 'pages'
- # safe_attributes 'isbn', :if => {|book, user| book.author == user}
- def safe_attributes(*args)
- @safe_attributes ||= []
- if args.empty?
- if superclass.include?(Redmine::SafeAttributes)
- @safe_attributes + superclass.safe_attributes
- else
- @safe_attributes
- end
- else
- options = args.last.is_a?(Hash) ? args.pop : {}
- @safe_attributes << [args, options]
- end
- end
- end
-
- # Returns an array that can be safely set by user or current user
- #
- # Example:
- # book.safe_attributes # => ['title', 'pages']
- # book.safe_attributes(book.author) # => ['title', 'pages', 'isbn']
- def safe_attribute_names(user=nil)
- return @safe_attribute_names if @safe_attribute_names && user.nil?
- names = []
- self.class.safe_attributes.collect do |attrs, options|
- if options[:if].nil? || options[:if].call(self, user || User.current)
- names += attrs.collect(&:to_s)
- end
- end
- names.uniq!
- @safe_attribute_names = names if user.nil?
- names
- end
-
- # Returns true if attr can be set by user or the current user
- def safe_attribute?(attr, user=nil)
- safe_attribute_names(user).include?(attr.to_s)
- end
-
- # Returns a hash with unsafe attributes removed
- # from the given attrs hash
- #
- # Example:
- # book.delete_unsafe_attributes({'title' => 'My book', 'foo' => 'bar'})
- # # => {'title' => 'My book'}
- def delete_unsafe_attributes(attrs, user=User.current)
- safe = safe_attribute_names(user)
- attrs.dup.delete_if {|k,v| !safe.include?(k)}
- end
-
- # Sets attributes from attrs that are safe
- # attrs is a Hash with string keys
- def safe_attributes=(attrs, user=User.current)
- return unless attrs.is_a?(Hash)
- self.attributes = delete_unsafe_attributes(attrs, user)
- end
- end
-end
diff --git a/trustie2/lib/redmine/scm/adapters/abstract_adapter.rb b/trustie2/lib/redmine/scm/adapters/abstract_adapter.rb
deleted file mode 100644
index 3e51f2d4d..000000000
--- a/trustie2/lib/redmine/scm/adapters/abstract_adapter.rb
+++ /dev/null
@@ -1,450 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'cgi'
-
-if RUBY_VERSION < '1.9'
- require 'iconv'
-end
-
-module Redmine
- module Scm
- module Adapters
- class CommandFailed < StandardError #:nodoc:
- end
-
- class AbstractAdapter #:nodoc:
-
- # raised if scm command exited with error, e.g. unknown revision.
- class ScmCommandAborted < CommandFailed; end
-
- class << self
- def client_command
- ""
- end
-
- def shell_quote_command
- if Redmine::Platform.mswin? && RUBY_PLATFORM == 'java'
- client_command
- else
- shell_quote(client_command)
- end
- end
-
- # Returns the version of the scm client
- # Eg: [1, 5, 0] or [] if unknown
- def client_version
- []
- end
-
- # Returns the version string of the scm client
- # Eg: '1.5.0' or 'Unknown version' if unknown
- def client_version_string
- v = client_version || 'Unknown version'
- v.is_a?(Array) ? v.join('.') : v.to_s
- end
-
- # Returns true if the current client version is above
- # or equals the given one
- # If option is :unknown is set to true, it will return
- # true if the client version is unknown
- def client_version_above?(v, options={})
- ((client_version <=> v) >= 0) || (client_version.empty? && options[:unknown])
- end
-
- def client_available
- true
- end
-
- def shell_quote(str)
- if Redmine::Platform.mswin?
- '"' + str.gsub(/"/, '\\"') + '"'
- else
- "'" + str.gsub(/'/, "'\"'\"'") + "'"
- end
- end
- end
-
- def initialize(url, root_url=nil, login=nil, password=nil,
- path_encoding=nil)
- @url = url
- @login = login if login && !login.empty?
- @password = (password || "") if @login
- @root_url = root_url.blank? ? retrieve_root_url : root_url
- end
-
- def adapter_name
- 'Abstract'
- end
-
- def supports_cat?
- true
- end
-
- def supports_annotate?
- respond_to?('annotate')
- end
-
- def root_url
- @root_url
- end
-
- def url
- @url
- end
-
- def path_encoding
- nil
- end
-
- # get info about the svn repository
- def info
- return nil
- end
-
- # Returns the entry identified by path and revision identifier
- # or nil if entry doesn't exist in the repository
- def entry(path=nil, identifier=nil)
- parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
- search_path = parts[0..-2].join('/')
- search_name = parts[-1]
- if search_path.blank? && search_name.blank?
- # Root entry
- Entry.new(:path => '', :kind => 'dir')
- else
- # Search for the entry in the parent directory
- es = entries(search_path, identifier)
- es ? es.detect {|e| e.name == search_name} : nil
- end
- end
-
- # Returns an Entries collection
- # or nil if the given path doesn't exist in the repository
- def entries(path=nil, identifier=nil, options={})
- return nil
- end
-
- def branches
- return nil
- end
-
- def tags
- return nil
- end
-
- def default_branch
- return nil
- end
-
- def properties(path, identifier=nil)
- return nil
- end
-
- def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
- return nil
- end
-
- def diff(path, identifier_from, identifier_to=nil)
- return nil
- end
-
- def cat(path, identifier=nil)
- return nil
- end
-
- def with_leading_slash(path)
- path ||= ''
- (path[0,1]!="/") ? "/#{path}" : path
- end
-
- def with_trailling_slash(path)
- path ||= ''
- (path[-1,1] == "/") ? path : "#{path}/"
- end
-
- def without_leading_slash(path)
- path ||= ''
- path.gsub(%r{^/+}, '')
- end
-
- def without_trailling_slash(path)
- path ||= ''
- (path[-1,1] == "/") ? path[0..-2] : path
- end
-
- def shell_quote(str)
- self.class.shell_quote(str)
- end
-
- private
- def retrieve_root_url
- info = self.info
- info ? info.root_url : nil
- end
-
- def target(path, sq=true)
- path ||= ''
- base = path.match(/^\//) ? root_url : url
- str = "#{base}/#{path}".gsub(/[?<>\*]/, '')
- if sq
- str = shell_quote(str)
- end
- str
- end
-
- def logger
- self.class.logger
- end
-
- def shellout(cmd, options = {}, &block)
- self.class.shellout(cmd, options, &block)
- end
-
- def self.logger
- Rails.logger
- end
-
- # Path to the file where scm stderr output is logged
- # Returns nil if the log file is not writable
- def self.stderr_log_file
- if @stderr_log_file.nil?
- writable = false
- path = Redmine::Configuration['scm_stderr_log_file'].presence
- path ||= Rails.root.join("log/#{Rails.env}.scm.stderr.log").to_s
- if File.exists?(path)
- if File.file?(path) && File.writable?(path)
- writable = true
- else
- logger.warn("SCM log file (#{path}) is not writable")
- end
- else
- begin
- File.open(path, "w") {}
- writable = true
- rescue => e
- logger.warn("SCM log file (#{path}) cannot be created: #{e.message}")
- end
- end
- @stderr_log_file = writable ? path : false
- end
- @stderr_log_file || nil
- end
-
- def self.shellout(cmd, options = {}, &block)
- if logger && logger.debug?
- logger.debug "Shelling out: #{strip_credential(cmd)}"
- # Capture stderr in a log file
- if stderr_log_file
- cmd = "#{cmd} 2>>#{shell_quote(stderr_log_file)}"
- end
- end
- begin
- mode = "r+"
- IO.popen(cmd, mode) do |io|
- io.set_encoding("ASCII-8BIT") if io.respond_to?(:set_encoding)
- io.close_write unless options[:write_stdin]
- block.call(io) if block_given?
- end
- ## If scm command does not exist,
- ## Linux JRuby 1.6.2 (ruby-1.8.7-p330) raises java.io.IOException
- ## in production environment.
- # rescue Errno::ENOENT => e
- rescue Exception => e
- msg = strip_credential(e.message)
- # The command failed, log it and re-raise
- logmsg = "SCM command failed, "
- logmsg += "make sure that your SCM command (e.g. svn) is "
- logmsg += "in PATH (#{ENV['PATH']})\n"
- logmsg += "You can configure your scm commands in config/configuration.yml.\n"
- logmsg += "#{strip_credential(cmd)}\n"
- logmsg += "with: #{msg}"
- logger.error(logmsg)
- raise CommandFailed.new(msg)
- end
- end
-
- # Hides username/password in a given command
- def self.strip_credential(cmd)
- q = (Redmine::Platform.mswin? ? '"' : "'")
- cmd.to_s.gsub(/(\-\-(password|username))\s+(#{q}[^#{q}]+#{q}|[^#{q}]\S+)/, '\\1 xxxx')
- end
-
- def strip_credential(cmd)
- self.class.strip_credential(cmd)
- end
-
- def scm_iconv(to, from, str)
- return nil if str.nil?
- return str if to == from
- if str.respond_to?(:force_encoding)
- str.force_encoding(from)
- begin
- str.encode(to)
- rescue Exception => err
- logger.error("failed to convert from #{from} to #{to}. #{err}")
- nil
- end
- else
- begin
- Iconv.conv(to, from, str)
- rescue Iconv::Failure => err
- logger.error("failed to convert from #{from} to #{to}. #{err}")
- nil
- end
- end
- end
-
- def parse_xml(xml)
- if RUBY_PLATFORM == 'java'
- xml = xml.sub(%r{<\?xml[^>]*\?>}, '')
- end
- ActiveSupport::XmlMini.parse(xml)
- end
- end
-
- class Entries < Array
- def sort_by_name
- dup.sort! {|x,y|
- if x.kind == y.kind
- x.name.to_s <=> y.name.to_s
- else
- x.kind <=> y.kind
- end
- }
- end
-
- def revisions
- revisions ||= Revisions.new(collect{|entry| entry.lastrev}.compact)
- end
- end
-
- class Info
- attr_accessor :root_url, :lastrev
- def initialize(attributes={})
- self.root_url = attributes[:root_url] if attributes[:root_url]
- self.lastrev = attributes[:lastrev]
- end
- end
-
- class Entry
- attr_accessor :name, :path, :kind, :size, :lastrev, :changeset
-
- def initialize(attributes={})
- self.name = attributes[:name] if attributes[:name]
- self.path = attributes[:path] if attributes[:path]
- self.kind = attributes[:kind] if attributes[:kind]
- self.size = attributes[:size].to_i if attributes[:size]
- self.lastrev = attributes[:lastrev]
- end
-
- def is_file?
- 'file' == self.kind
- end
-
- def is_dir?
- 'dir' == self.kind
- end
-
- def is_text?
- Redmine::MimeType.is_type?('text', name)
- end
-
- def author
- if changeset
- changeset.author.to_s
- elsif lastrev
- Redmine::CodesetUtil.replace_invalid_utf8(lastrev.author.to_s.split('<').first)
- end
- end
- end
-
- class Revisions < Array
- def latest
- sort {|x,y|
- unless x.time.nil? or y.time.nil?
- x.time <=> y.time
- else
- 0
- end
- }.last
- end
- end
-
- class Revision
- attr_accessor :scmid, :name, :author, :time, :message,
- :paths, :revision, :branch, :identifier,
- :parents
-
- def initialize(attributes={})
- self.identifier = attributes[:identifier]
- self.scmid = attributes[:scmid]
- self.name = attributes[:name] || self.identifier
- self.author = attributes[:author]
- self.time = attributes[:time]
- self.message = attributes[:message] || ""
- self.paths = attributes[:paths]
- self.revision = attributes[:revision]
- self.branch = attributes[:branch]
- self.parents = attributes[:parents]
- end
-
- # Returns the readable identifier.
- def format_identifier
- self.identifier.to_s
- end
-
- def ==(other)
- if other.nil?
- false
- elsif scmid.present?
- scmid == other.scmid
- elsif identifier.present?
- identifier == other.identifier
- elsif revision.present?
- revision == other.revision
- end
- end
- end
-
- class Annotate
- attr_reader :lines, :revisions
-
- def initialize
- @lines = []
- @revisions = []
- end
-
- def add_line(line, revision)
- @lines << line
- @revisions << revision
- end
-
- def content
- content = lines.join("\n")
- end
-
- def empty?
- lines.empty?
- end
- end
-
- class Branch < String
- attr_accessor :revision, :scmid
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/scm/adapters/bazaar_adapter.rb b/trustie2/lib/redmine/scm/adapters/bazaar_adapter.rb
deleted file mode 100644
index 8de831d6c..000000000
--- a/trustie2/lib/redmine/scm/adapters/bazaar_adapter.rb
+++ /dev/null
@@ -1,341 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'redmine/scm/adapters/abstract_adapter'
-
-module Redmine
- module Scm
- module Adapters
- class BazaarAdapter < AbstractAdapter
-
- # Bazaar executable name
- BZR_BIN = Redmine::Configuration['scm_bazaar_command'] || "bzr"
-
- class << self
- def client_command
- @@bin ||= BZR_BIN
- end
-
- def sq_bin
- @@sq_bin ||= shell_quote_command
- end
-
- def client_version
- @@client_version ||= (scm_command_version || [])
- end
-
- def client_available
- !client_version.empty?
- end
-
- def scm_command_version
- scm_version = scm_version_from_command_line.dup
- if scm_version.respond_to?(:force_encoding)
- scm_version.force_encoding('ASCII-8BIT')
- end
- if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
- m[2].scan(%r{\d+}).collect(&:to_i)
- end
- end
-
- def scm_version_from_command_line
- shellout("#{sq_bin} --version") { |io| io.read }.to_s
- end
- end
-
- def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
- @url = url
- @root_url = url
- @path_encoding = 'UTF-8'
- # do not call *super* for non ASCII repository path
- end
-
- def bzr_path_encodig=(encoding)
- @path_encoding = encoding
- end
-
- # Get info about the repository
- def info
- cmd_args = %w|revno|
- cmd_args << bzr_target('')
- info = nil
- scm_cmd(*cmd_args) do |io|
- if io.read =~ %r{^(\d+)\r?$}
- info = Info.new({:root_url => url,
- :lastrev => Revision.new({
- :identifier => $1
- })
- })
- end
- end
- info
- rescue ScmCommandAborted
- return nil
- end
-
- # Returns an Entries collection
- # or nil if the given path doesn't exist in the repository
- def entries(path=nil, identifier=nil, options={})
- path ||= ''
- entries = Entries.new
- identifier = -1 unless identifier && identifier.to_i > 0
- cmd_args = %w|ls -v --show-ids|
- cmd_args << "-r#{identifier.to_i}"
- cmd_args << bzr_target(path)
- scm_cmd(*cmd_args) do |io|
- prefix_utf8 = "#{url}/#{path}".gsub('\\', '/')
- logger.debug "PREFIX: #{prefix_utf8}"
- prefix = scm_iconv(@path_encoding, 'UTF-8', prefix_utf8)
- prefix.force_encoding('ASCII-8BIT') if prefix.respond_to?(:force_encoding)
- re = %r{^V\s+(#{Regexp.escape(prefix)})?(\/?)([^\/]+)(\/?)\s+(\S+)\r?$}
- io.each_line do |line|
- next unless line =~ re
- name_locale, slash, revision = $3.strip, $4, $5.strip
- name = scm_iconv('UTF-8', @path_encoding, name_locale)
- entries << Entry.new({:name => name,
- :path => ((path.empty? ? "" : "#{path}/") + name),
- :kind => (slash.blank? ? 'file' : 'dir'),
- :size => nil,
- :lastrev => Revision.new(:revision => revision)
- })
- end
- end
- if logger && logger.debug?
- logger.debug("Found #{entries.size} entries in the repository for #{target(path)}")
- end
- entries.sort_by_name
- rescue ScmCommandAborted
- return nil
- end
-
- def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
- path ||= ''
- identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : 'last:1'
- identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : 1
- revisions = Revisions.new
- cmd_args = %w|log -v --show-ids|
- cmd_args << "-r#{identifier_to}..#{identifier_from}"
- cmd_args << bzr_target(path)
- scm_cmd(*cmd_args) do |io|
- revision = nil
- parsing = nil
- io.each_line do |line|
- if line =~ /^----/
- revisions << revision if revision
- revision = Revision.new(:paths => [], :message => '')
- parsing = nil
- else
- next unless revision
- if line =~ /^revno: (\d+)($|\s\[merge\]$)/
- revision.identifier = $1.to_i
- elsif line =~ /^committer: (.+)$/
- revision.author = $1.strip
- elsif line =~ /^revision-id:(.+)$/
- revision.scmid = $1.strip
- elsif line =~ /^timestamp: (.+)$/
- revision.time = Time.parse($1).localtime
- elsif line =~ /^ -----/
- # partial revisions
- parsing = nil unless parsing == 'message'
- elsif line =~ /^(message|added|modified|removed|renamed):/
- parsing = $1
- elsif line =~ /^ (.*)$/
- if parsing == 'message'
- revision.message << "#{$1}\n"
- else
- if $1 =~ /^(.*)\s+(\S+)$/
- path_locale = $1.strip
- path = scm_iconv('UTF-8', @path_encoding, path_locale)
- revid = $2
- case parsing
- when 'added'
- revision.paths << {:action => 'A', :path => "/#{path}", :revision => revid}
- when 'modified'
- revision.paths << {:action => 'M', :path => "/#{path}", :revision => revid}
- when 'removed'
- revision.paths << {:action => 'D', :path => "/#{path}", :revision => revid}
- when 'renamed'
- new_path = path.split('=>').last
- if new_path
- revision.paths << {:action => 'M', :path => "/#{new_path.strip}",
- :revision => revid}
- end
- end
- end
- end
- else
- parsing = nil
- end
- end
- end
- revisions << revision if revision
- end
- revisions
- rescue ScmCommandAborted
- return nil
- end
-
- def diff(path, identifier_from, identifier_to=nil)
- path ||= ''
- if identifier_to
- identifier_to = identifier_to.to_i
- else
- identifier_to = identifier_from.to_i - 1
- end
- if identifier_from
- identifier_from = identifier_from.to_i
- end
- diff = []
- cmd_args = %w|diff|
- cmd_args << "-r#{identifier_to}..#{identifier_from}"
- cmd_args << bzr_target(path)
- scm_cmd_no_raise(*cmd_args) do |io|
- io.each_line do |line|
- diff << line
- end
- end
- diff
- end
-
- def cat(path, identifier=nil)
- cat = nil
- cmd_args = %w|cat|
- cmd_args << "-r#{identifier.to_i}" if identifier && identifier.to_i > 0
- cmd_args << bzr_target(path)
- scm_cmd(*cmd_args) do |io|
- io.binmode
- cat = io.read
- end
- cat
- rescue ScmCommandAborted
- return nil
- end
-
- def annotate(path, identifier=nil)
- blame = Annotate.new
- cmd_args = %w|annotate -q --all|
- cmd_args << "-r#{identifier.to_i}" if identifier && identifier.to_i > 0
- cmd_args << bzr_target(path)
- scm_cmd(*cmd_args) do |io|
- author = nil
- identifier = nil
- io.each_line do |line|
- next unless line =~ %r{^(\d+) ([^|]+)\| (.*)$}
- rev = $1
- blame.add_line($3.rstrip,
- Revision.new(
- :identifier => rev,
- :revision => rev,
- :author => $2.strip
- ))
- end
- end
- blame
- rescue ScmCommandAborted
- return nil
- end
-
- def self.branch_conf_path(path)
- bcp = nil
- m = path.match(%r{^(.*[/\\])\.bzr.*$})
- if m
- bcp = m[1]
- else
- bcp = path
- end
- bcp.gsub!(%r{[\/\\]$}, "")
- if bcp
- bcp = File.join(bcp, ".bzr", "branch", "branch.conf")
- end
- bcp
- end
-
- def append_revisions_only
- return @aro if ! @aro.nil?
- @aro = false
- bcp = self.class.branch_conf_path(url)
- if bcp && File.exist?(bcp)
- begin
- f = File::open(bcp, "r")
- cnt = 0
- f.each_line do |line|
- l = line.chomp.to_s
- if l =~ /^\s*append_revisions_only\s*=\s*(\w+)\s*$/
- str_aro = $1
- if str_aro.upcase == "TRUE"
- @aro = true
- cnt += 1
- elsif str_aro.upcase == "FALSE"
- @aro = false
- cnt += 1
- end
- if cnt > 1
- @aro = false
- break
- end
- end
- end
- ensure
- f.close
- end
- end
- @aro
- end
-
- def scm_cmd(*args, &block)
- full_args = []
- full_args += args
- full_args_locale = []
- full_args.map do |e|
- full_args_locale << scm_iconv(@path_encoding, 'UTF-8', e)
- end
- ret = shellout(
- self.class.sq_bin + ' ' +
- full_args_locale.map { |e| shell_quote e.to_s }.join(' '),
- &block
- )
- if $? && $?.exitstatus != 0
- raise ScmCommandAborted, "bzr exited with non-zero status: #{$?.exitstatus}"
- end
- ret
- end
- private :scm_cmd
-
- def scm_cmd_no_raise(*args, &block)
- full_args = []
- full_args += args
- full_args_locale = []
- full_args.map do |e|
- full_args_locale << scm_iconv(@path_encoding, 'UTF-8', e)
- end
- ret = shellout(
- self.class.sq_bin + ' ' +
- full_args_locale.map { |e| shell_quote e.to_s }.join(' '),
- &block
- )
- ret
- end
- private :scm_cmd_no_raise
-
- def bzr_target(path)
- target(path, false)
- end
- private :bzr_target
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/scm/adapters/cvs_adapter.rb b/trustie2/lib/redmine/scm/adapters/cvs_adapter.rb
deleted file mode 100644
index 3a0d27c34..000000000
--- a/trustie2/lib/redmine/scm/adapters/cvs_adapter.rb
+++ /dev/null
@@ -1,462 +0,0 @@
-# redMine - project management software
-# Copyright (C) 2006-2007 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 'redmine/scm/adapters/abstract_adapter'
-
-module Redmine
- module Scm
- module Adapters
- class CvsAdapter < AbstractAdapter
-
- # CVS executable name
- CVS_BIN = Redmine::Configuration['scm_cvs_command'] || "cvs"
-
- class << self
- def client_command
- @@bin ||= CVS_BIN
- end
-
- def sq_bin
- @@sq_bin ||= shell_quote_command
- end
-
- def client_version
- @@client_version ||= (scm_command_version || [])
- end
-
- def client_available
- client_version_above?([1, 12])
- end
-
- def scm_command_version
- scm_version = scm_version_from_command_line.dup
- if scm_version.respond_to?(:force_encoding)
- scm_version.force_encoding('ASCII-8BIT')
- end
- if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)}m)
- m[2].scan(%r{\d+}).collect(&:to_i)
- end
- end
-
- def scm_version_from_command_line
- shellout("#{sq_bin} --version") { |io| io.read }.to_s
- end
- end
-
- # Guidelines for the input:
- # url -> the project-path, relative to the cvsroot (eg. module name)
- # root_url -> the good old, sometimes damned, CVSROOT
- # login -> unnecessary
- # password -> unnecessary too
- def initialize(url, root_url=nil, login=nil, password=nil,
- path_encoding=nil)
- @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
- @url = url
- # TODO: better Exception here (IllegalArgumentException)
- raise CommandFailed if root_url.blank?
- @root_url = root_url
-
- # These are unused.
- @login = login if login && !login.empty?
- @password = (password || "") if @login
- end
-
- def path_encoding
- @path_encoding
- end
-
- def info
- logger.debug " info"
- Info.new({:root_url => @root_url, :lastrev => nil})
- end
-
- def get_previous_revision(revision)
- CvsRevisionHelper.new(revision).prevRev
- end
-
- # Returns an Entries collection
- # or nil if the given path doesn't exist in the repository
- # this method is used by the repository-browser (aka LIST)
- def entries(path=nil, identifier=nil, options={})
- logger.debug " entries '#{path}' with identifier '#{identifier}'"
- path_locale = scm_iconv(@path_encoding, 'UTF-8', path)
- path_locale.force_encoding("ASCII-8BIT") if path_locale.respond_to?(:force_encoding)
- entries = Entries.new
- cmd_args = %w|-q rls -e|
- cmd_args << "-D" << time_to_cvstime_rlog(identifier) if identifier
- cmd_args << path_with_proj(path)
- scm_cmd(*cmd_args) do |io|
- io.each_line() do |line|
- fields = line.chop.split('/',-1)
- logger.debug(">>InspectLine #{fields.inspect}")
- if fields[0]!="D"
- time = nil
- # Thu Dec 13 16:27:22 2007
- time_l = fields[-3].split(' ')
- if time_l.size == 5 && time_l[4].length == 4
- begin
- time = Time.parse(
- "#{time_l[1]} #{time_l[2]} #{time_l[3]} GMT #{time_l[4]}")
- rescue
- end
- end
- entries << Entry.new(
- {
- :name => scm_iconv('UTF-8', @path_encoding, fields[-5]),
- #:path => fields[-4].include?(path)?fields[-4]:(path + "/"+ fields[-4]),
- :path => scm_iconv('UTF-8', @path_encoding, "#{path_locale}/#{fields[-5]}"),
- :kind => 'file',
- :size => nil,
- :lastrev => Revision.new(
- {
- :revision => fields[-4],
- :name => scm_iconv('UTF-8', @path_encoding, fields[-4]),
- :time => time,
- :author => ''
- })
- })
- else
- entries << Entry.new(
- {
- :name => scm_iconv('UTF-8', @path_encoding, fields[1]),
- :path => scm_iconv('UTF-8', @path_encoding, "#{path_locale}/#{fields[1]}"),
- :kind => 'dir',
- :size => nil,
- :lastrev => nil
- })
- end
- end
- end
- entries.sort_by_name
- rescue ScmCommandAborted
- nil
- end
-
- STARTLOG="----------------------------"
- ENDLOG ="============================================================================="
-
- # Returns all revisions found between identifier_from and identifier_to
- # in the repository. both identifier have to be dates or nil.
- # these method returns nothing but yield every result in block
- def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={}, &block)
- path_with_project_utf8 = path_with_proj(path)
- path_with_project_locale = scm_iconv(@path_encoding, 'UTF-8', path_with_project_utf8)
- logger.debug " revisions path:" +
- "'#{path}',identifier_from #{identifier_from}, identifier_to #{identifier_to}"
- cmd_args = %w|-q rlog|
- cmd_args << "-d" << ">#{time_to_cvstime_rlog(identifier_from)}" if identifier_from
- cmd_args << path_with_project_utf8
- scm_cmd(*cmd_args) do |io|
- state = "entry_start"
- commit_log = String.new
- revision = nil
- date = nil
- author = nil
- entry_path = nil
- entry_name = nil
- file_state = nil
- branch_map = nil
- io.each_line() do |line|
- if state != "revision" && /^#{ENDLOG}/ =~ line
- commit_log = String.new
- revision = nil
- state = "entry_start"
- end
- if state == "entry_start"
- branch_map = Hash.new
- if /^RCS file: #{Regexp.escape(root_url_path)}\/#{Regexp.escape(path_with_project_locale)}(.+),v$/ =~ line
- entry_path = normalize_cvs_path($1)
- entry_name = normalize_path(File.basename($1))
- logger.debug("Path #{entry_path} <=> Name #{entry_name}")
- elsif /^head: (.+)$/ =~ line
- entry_headRev = $1 #unless entry.nil?
- elsif /^symbolic names:/ =~ line
- state = "symbolic" #unless entry.nil?
- elsif /^#{STARTLOG}/ =~ line
- commit_log = String.new
- state = "revision"
- end
- next
- elsif state == "symbolic"
- if /^(.*):\s(.*)/ =~ (line.strip)
- branch_map[$1] = $2
- else
- state = "tags"
- next
- end
- elsif state == "tags"
- if /^#{STARTLOG}/ =~ line
- commit_log = ""
- state = "revision"
- elsif /^#{ENDLOG}/ =~ line
- state = "head"
- end
- next
- elsif state == "revision"
- if /^#{ENDLOG}/ =~ line || /^#{STARTLOG}/ =~ line
- if revision
- revHelper = CvsRevisionHelper.new(revision)
- revBranch = "HEAD"
- branch_map.each() do |branch_name, branch_point|
- if revHelper.is_in_branch_with_symbol(branch_point)
- revBranch = branch_name
- end
- end
- logger.debug("********** YIELD Revision #{revision}::#{revBranch}")
- yield Revision.new({
- :time => date,
- :author => author,
- :message => commit_log.chomp,
- :paths => [{
- :revision => revision.dup,
- :branch => revBranch.dup,
- :path => scm_iconv('UTF-8', @path_encoding, entry_path),
- :name => scm_iconv('UTF-8', @path_encoding, entry_name),
- :kind => 'file',
- :action => file_state
- }]
- })
- end
- commit_log = String.new
- revision = nil
- if /^#{ENDLOG}/ =~ line
- state = "entry_start"
- end
- next
- end
-
- if /^branches: (.+)$/ =~ line
- # TODO: version.branch = $1
- elsif /^revision (\d+(?:\.\d+)+).*$/ =~ line
- revision = $1
- elsif /^date:\s+(\d+.\d+.\d+\s+\d+:\d+:\d+)/ =~ line
- date = Time.parse($1)
- line_utf8 = scm_iconv('UTF-8', options[:log_encoding], line)
- author_utf8 = /author: ([^;]+)/.match(line_utf8)[1]
- author = scm_iconv(options[:log_encoding], 'UTF-8', author_utf8)
- file_state = /state: ([^;]+)/.match(line)[1]
- # TODO:
- # linechanges only available in CVS....
- # maybe a feature our SVN implementation.
- # I'm sure, they are useful for stats or something else
- # linechanges =/lines: \+(\d+) -(\d+)/.match(line)
- # unless linechanges.nil?
- # version.line_plus = linechanges[1]
- # version.line_minus = linechanges[2]
- # else
- # version.line_plus = 0
- # version.line_minus = 0
- # end
- else
- commit_log << line unless line =~ /^\*\*\* empty log message \*\*\*/
- end
- end
- end
- end
- rescue ScmCommandAborted
- Revisions.new
- end
-
- def diff(path, identifier_from, identifier_to=nil)
- logger.debug " diff path:'#{path}'" +
- ",identifier_from #{identifier_from}, identifier_to #{identifier_to}"
- cmd_args = %w|rdiff -u|
- cmd_args << "-r#{identifier_to}"
- cmd_args << "-r#{identifier_from}"
- cmd_args << path_with_proj(path)
- diff = []
- scm_cmd(*cmd_args) do |io|
- io.each_line do |line|
- diff << line
- end
- end
- diff
- rescue ScmCommandAborted
- nil
- end
-
- def cat(path, identifier=nil)
- identifier = (identifier) ? identifier : "HEAD"
- logger.debug " cat path:'#{path}',identifier #{identifier}"
- cmd_args = %w|-q co|
- cmd_args << "-D" << time_to_cvstime(identifier) if identifier
- cmd_args << "-p" << path_with_proj(path)
- cat = nil
- scm_cmd(*cmd_args) do |io|
- io.binmode
- cat = io.read
- end
- cat
- rescue ScmCommandAborted
- nil
- end
-
- def annotate(path, identifier=nil)
- identifier = (identifier) ? identifier : "HEAD"
- logger.debug " annotate path:'#{path}',identifier #{identifier}"
- cmd_args = %w|rannotate|
- cmd_args << "-D" << time_to_cvstime(identifier) if identifier
- cmd_args << path_with_proj(path)
- blame = Annotate.new
- scm_cmd(*cmd_args) do |io|
- io.each_line do |line|
- next unless line =~ %r{^([\d\.]+)\s+\(([^\)]+)\s+[^\)]+\):\s(.*)$}
- blame.add_line(
- $3.rstrip,
- Revision.new(
- :revision => $1,
- :identifier => nil,
- :author => $2.strip
- ))
- end
- end
- blame
- rescue ScmCommandAborted
- Annotate.new
- end
-
- private
-
- # Returns the root url without the connexion string
- # :pserver:anonymous@foo.bar:/path => /path
- # :ext:cvsservername:/path => /path
- def root_url_path
- root_url.to_s.gsub(/^:.+:\d*/, '')
- end
-
- # convert a date/time into the CVS-format
- def time_to_cvstime(time)
- return nil if time.nil?
- time = Time.now if time == 'HEAD'
-
- unless time.kind_of? Time
- time = Time.parse(time)
- end
- return time_to_cvstime_rlog(time)
- end
-
- def time_to_cvstime_rlog(time)
- return nil if time.nil?
- t1 = time.clone.localtime
- return t1.strftime("%Y-%m-%d %H:%M:%S")
- end
-
- def normalize_cvs_path(path)
- normalize_path(path.gsub(/Attic\//,''))
- end
-
- def normalize_path(path)
- path.sub(/^(\/)*(.*)/,'\2').sub(/(.*)(,v)+/,'\1')
- end
-
- def path_with_proj(path)
- "#{url}#{with_leading_slash(path)}"
- end
- private :path_with_proj
-
- class Revision < Redmine::Scm::Adapters::Revision
- # Returns the readable identifier
- def format_identifier
- revision.to_s
- end
- end
-
- def scm_cmd(*args, &block)
- full_args = ['-d', root_url]
- full_args += args
- full_args_locale = []
- full_args.map do |e|
- full_args_locale << scm_iconv(@path_encoding, 'UTF-8', e)
- end
- ret = shellout(
- self.class.sq_bin + ' ' + full_args_locale.map { |e| shell_quote e.to_s }.join(' '),
- &block
- )
- if $? && $?.exitstatus != 0
- raise ScmCommandAborted, "cvs exited with non-zero status: #{$?.exitstatus}"
- end
- ret
- end
- private :scm_cmd
- end
-
- class CvsRevisionHelper
- attr_accessor :complete_rev, :revision, :base, :branchid
-
- def initialize(complete_rev)
- @complete_rev = complete_rev
- parseRevision()
- end
-
- def branchPoint
- return @base
- end
-
- def branchVersion
- if isBranchRevision
- return @base+"."+@branchid
- end
- return @base
- end
-
- def isBranchRevision
- !@branchid.nil?
- end
-
- def prevRev
- unless @revision == 0
- return buildRevision( @revision - 1 )
- end
- return buildRevision( @revision )
- end
-
- def is_in_branch_with_symbol(branch_symbol)
- bpieces = branch_symbol.split(".")
- branch_start = "#{bpieces[0..-3].join(".")}.#{bpieces[-1]}"
- return ( branchVersion == branch_start )
- end
-
- private
- def buildRevision(rev)
- if rev == 0
- if @branchid.nil?
- @base + ".0"
- else
- @base
- end
- elsif @branchid.nil?
- @base + "." + rev.to_s
- else
- @base + "." + @branchid + "." + rev.to_s
- end
- end
-
- # Interpretiert die cvs revisionsnummern wie z.b. 1.14 oder 1.3.0.15
- def parseRevision()
- pieces = @complete_rev.split(".")
- @revision = pieces.last.to_i
- baseSize = 1
- baseSize += (pieces.size / 2)
- @base = pieces[0..-baseSize].join(".")
- if baseSize > 2
- @branchid = pieces[-2]
- end
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/scm/adapters/darcs_adapter.rb b/trustie2/lib/redmine/scm/adapters/darcs_adapter.rb
deleted file mode 100644
index 348bd4d0f..000000000
--- a/trustie2/lib/redmine/scm/adapters/darcs_adapter.rb
+++ /dev/null
@@ -1,242 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'redmine/scm/adapters/abstract_adapter'
-require 'rexml/document'
-
-module Redmine
- module Scm
- module Adapters
- class DarcsAdapter < AbstractAdapter
- # Darcs executable name
- DARCS_BIN = Redmine::Configuration['scm_darcs_command'] || "darcs"
-
- class << self
- def client_command
- @@bin ||= DARCS_BIN
- end
-
- def sq_bin
- @@sq_bin ||= shell_quote_command
- end
-
- def client_version
- @@client_version ||= (darcs_binary_version || [])
- end
-
- def client_available
- !client_version.empty?
- end
-
- def darcs_binary_version
- darcsversion = darcs_binary_version_from_command_line.dup
- if darcsversion.respond_to?(:force_encoding)
- darcsversion.force_encoding('ASCII-8BIT')
- end
- if m = darcsversion.match(%r{\A(.*?)((\d+\.)+\d+)})
- m[2].scan(%r{\d+}).collect(&:to_i)
- end
- end
-
- def darcs_binary_version_from_command_line
- shellout("#{sq_bin} --version") { |io| io.read }.to_s
- end
- end
-
- def initialize(url, root_url=nil, login=nil, password=nil,
- path_encoding=nil)
- @url = url
- @root_url = url
- end
-
- def supports_cat?
- # cat supported in darcs 2.0.0 and higher
- self.class.client_version_above?([2, 0, 0])
- end
-
- # Get info about the darcs repository
- def info
- rev = revisions(nil,nil,nil,{:limit => 1})
- rev ? Info.new({:root_url => @url, :lastrev => rev.last}) : nil
- end
-
- # Returns an Entries collection
- # or nil if the given path doesn't exist in the repository
- def entries(path=nil, identifier=nil, options={})
- path_prefix = (path.blank? ? '' : "#{path}/")
- if path.blank?
- path = ( self.class.client_version_above?([2, 2, 0]) ? @url : '.' )
- end
- entries = Entries.new
- cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --xml-output"
- cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier
- cmd << " #{shell_quote path}"
- shellout(cmd) do |io|
- begin
- doc = REXML::Document.new(io)
- if doc.root.name == 'directory'
- doc.elements.each('directory/*') do |element|
- next unless ['file', 'directory'].include? element.name
- entries << entry_from_xml(element, path_prefix)
- end
- elsif doc.root.name == 'file'
- entries << entry_from_xml(doc.root, path_prefix)
- end
- rescue
- end
- end
- return nil if $? && $?.exitstatus != 0
- entries.compact!
- entries.sort_by_name
- end
-
- def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
- path = '.' if path.blank?
- revisions = Revisions.new
- cmd = "#{self.class.sq_bin} changes --repodir #{shell_quote @url} --xml-output"
- cmd << " --from-match #{shell_quote("hash #{identifier_from}")}" if identifier_from
- cmd << " --last #{options[:limit].to_i}" if options[:limit]
- shellout(cmd) do |io|
- begin
- doc = REXML::Document.new(io)
- doc.elements.each("changelog/patch") do |patch|
- message = patch.elements['name'].text
- message << "\n" + patch.elements['comment'].text.gsub(/\*\*\*END OF DESCRIPTION\*\*\*.*\z/m, '') if patch.elements['comment']
- revisions << Revision.new({:identifier => nil,
- :author => patch.attributes['author'],
- :scmid => patch.attributes['hash'],
- :time => Time.parse(patch.attributes['local_date']),
- :message => message,
- :paths => (options[:with_path] ? get_paths_for_patch(patch.attributes['hash']) : nil)
- })
- end
- rescue
- end
- end
- return nil if $? && $?.exitstatus != 0
- revisions
- end
-
- def diff(path, identifier_from, identifier_to=nil)
- path = '*' if path.blank?
- cmd = "#{self.class.sq_bin} diff --repodir #{shell_quote @url}"
- if identifier_to.nil?
- cmd << " --match #{shell_quote("hash #{identifier_from}")}"
- else
- cmd << " --to-match #{shell_quote("hash #{identifier_from}")}"
- cmd << " --from-match #{shell_quote("hash #{identifier_to}")}"
- end
- cmd << " -u #{shell_quote path}"
- diff = []
- shellout(cmd) do |io|
- io.each_line do |line|
- diff << line
- end
- end
- return nil if $? && $?.exitstatus != 0
- diff
- end
-
- def cat(path, identifier=nil)
- cmd = "#{self.class.sq_bin} show content --repodir #{shell_quote @url}"
- cmd << " --match #{shell_quote("hash #{identifier}")}" if identifier
- cmd << " #{shell_quote path}"
- cat = nil
- shellout(cmd) do |io|
- io.binmode
- cat = io.read
- end
- return nil if $? && $?.exitstatus != 0
- cat
- end
-
- private
-
- # Returns an Entry from the given XML element
- # or nil if the entry was deleted
- def entry_from_xml(element, path_prefix)
- modified_element = element.elements['modified']
- if modified_element.elements['modified_how'].text.match(/removed/)
- return nil
- end
-
- Entry.new({:name => element.attributes['name'],
- :path => path_prefix + element.attributes['name'],
- :kind => element.name == 'file' ? 'file' : 'dir',
- :size => nil,
- :lastrev => Revision.new({
- :identifier => nil,
- :scmid => modified_element.elements['patch'].attributes['hash']
- })
- })
- end
-
- def get_paths_for_patch(hash)
- paths = get_paths_for_patch_raw(hash)
- if self.class.client_version_above?([2, 4])
- orig_paths = paths
- paths = []
- add_paths = []
- add_paths_name = []
- mod_paths = []
- other_paths = []
- orig_paths.each do |path|
- if path[:action] == 'A'
- add_paths << path
- add_paths_name << path[:path]
- elsif path[:action] == 'M'
- mod_paths << path
- else
- other_paths << path
- end
- end
- add_paths_name.each do |add_path|
- mod_paths.delete_if { |m| m[:path] == add_path }
- end
- paths.concat add_paths
- paths.concat mod_paths
- paths.concat other_paths
- end
- paths
- end
-
- # Retrieve changed paths for a single patch
- def get_paths_for_patch_raw(hash)
- cmd = "#{self.class.sq_bin} annotate --repodir #{shell_quote @url} --summary --xml-output"
- cmd << " --match #{shell_quote("hash #{hash}")} "
- paths = []
- shellout(cmd) do |io|
- begin
- # Darcs xml output has multiple root elements in this case (tested with darcs 1.0.7)
- # A root element is added so that REXML doesn't raise an error
- doc = REXML::Document.new("" + io.read + " ")
- doc.elements.each('fake_root/summary/*') do |modif|
- paths << {:action => modif.name[0,1].upcase,
- :path => "/" + modif.text.chomp.gsub(/^\s*/, '')
- }
- end
- rescue
- end
- end
- paths
- rescue CommandFailed
- paths
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/scm/adapters/filesystem_adapter.rb b/trustie2/lib/redmine/scm/adapters/filesystem_adapter.rb
deleted file mode 100644
index 2ce82b97c..000000000
--- a/trustie2/lib/redmine/scm/adapters/filesystem_adapter.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 Jean-Philippe Lang
-#
-# FileSystem adapter
-# File written by Paul Rivier, at Demotera.
-#
-# 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 'redmine/scm/adapters/abstract_adapter'
-require 'find'
-
-module Redmine
- module Scm
- module Adapters
- class FilesystemAdapter < AbstractAdapter
-
- class << self
- def client_available
- true
- end
- end
-
- def initialize(url, root_url=nil, login=nil, password=nil,
- path_encoding=nil)
- @url = with_trailling_slash(url)
- @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
- end
-
- def path_encoding
- @path_encoding
- end
-
- def format_path_ends(path, leading=true, trailling=true)
- path = leading ? with_leading_slash(path) :
- without_leading_slash(path)
- trailling ? with_trailling_slash(path) :
- without_trailling_slash(path)
- end
-
- def info
- info = Info.new({:root_url => target(),
- :lastrev => nil
- })
- info
- rescue CommandFailed
- return nil
- end
-
- def entries(path="", identifier=nil, options={})
- entries = Entries.new
- trgt_utf8 = target(path)
- trgt = scm_iconv(@path_encoding, 'UTF-8', trgt_utf8)
- Dir.new(trgt).each do |e1|
- e_utf8 = scm_iconv('UTF-8', @path_encoding, e1)
- next if e_utf8.blank?
- relative_path_utf8 = format_path_ends(
- (format_path_ends(path,false,true) + e_utf8),false,false)
- t1_utf8 = target(relative_path_utf8)
- t1 = scm_iconv(@path_encoding, 'UTF-8', t1_utf8)
- relative_path = scm_iconv(@path_encoding, 'UTF-8', relative_path_utf8)
- e1 = scm_iconv(@path_encoding, 'UTF-8', e_utf8)
- if File.exist?(t1) and # paranoid test
- %w{file directory}.include?(File.ftype(t1)) and # avoid special types
- not File.basename(e1).match(/^\.+$/) # avoid . and ..
- p1 = File.readable?(t1) ? relative_path : ""
- utf_8_path = scm_iconv('UTF-8', @path_encoding, p1)
- entries <<
- Entry.new({ :name => scm_iconv('UTF-8', @path_encoding, File.basename(e1)),
- # below : list unreadable files, but dont link them.
- :path => utf_8_path,
- :kind => (File.directory?(t1) ? 'dir' : 'file'),
- :size => (File.directory?(t1) ? nil : [File.size(t1)].pack('l').unpack('L').first),
- :lastrev =>
- Revision.new({:time => (File.mtime(t1)) })
- })
- end
- end
- entries.sort_by_name
- rescue => err
- logger.error "scm: filesystem: error: #{err.message}"
- raise CommandFailed.new(err.message)
- end
-
- def cat(path, identifier=nil)
- p = scm_iconv(@path_encoding, 'UTF-8', target(path))
- File.new(p, "rb").read
- rescue => err
- logger.error "scm: filesystem: error: #{err.message}"
- raise CommandFailed.new(err.message)
- end
-
- private
-
- # AbstractAdapter::target is implicitly made to quote paths.
- # Here we do not shell-out, so we do not want quotes.
- def target(path=nil)
- # Prevent the use of ..
- if path and !path.match(/(^|\/)\.\.(\/|$)/)
- return "#{self.url}#{without_leading_slash(path)}"
- end
- return self.url
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/scm/adapters/git_adapter.rb b/trustie2/lib/redmine/scm/adapters/git_adapter.rb
deleted file mode 100644
index 1876190d9..000000000
--- a/trustie2/lib/redmine/scm/adapters/git_adapter.rb
+++ /dev/null
@@ -1,412 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'redmine/scm/adapters/abstract_adapter'
-
-module Redmine
- module Scm
- module Adapters
- class GitAdapter < AbstractAdapter
-
- # Git executable name
- GIT_BIN = Redmine::Configuration['scm_git_command'] || "git"
-
- class GitBranch < Branch
- attr_accessor :is_default
- end
-
- class << self
- def client_command
- @@bin ||= GIT_BIN
- end
-
- def sq_bin
- @@sq_bin ||= shell_quote_command
- end
-
- def client_version
- @@client_version ||= (scm_command_version || [])
- end
-
- def client_available
- !client_version.empty?
- end
-
- def scm_command_version
- scm_version = scm_version_from_command_line.dup
- if scm_version.respond_to?(:force_encoding)
- scm_version.force_encoding('ASCII-8BIT')
- end
- if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
- m[2].scan(%r{\d+}).collect(&:to_i)
- end
- end
-
- def scm_version_from_command_line
- shellout("#{sq_bin} --version --no-color") { |io| io.read }.to_s
- end
- end
-
- def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
- super
- @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
- end
-
- def path_encoding
- @path_encoding
- end
-
- def info
- begin
- Info.new(:root_url => url, :lastrev => lastrev('',nil))
- rescue
- nil
- end
- end
-
- def branches
- return @branches if @branches
- @branches = []
- cmd_args = %w|branch --no-color --verbose --no-abbrev|
- git_cmd(cmd_args) do |io|
- io.each_line do |line|
- branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$')
- bran = GitBranch.new(branch_rev[2])
- bran.revision = branch_rev[3]
- bran.scmid = branch_rev[3]
- bran.is_default = ( branch_rev[1] == '*' )
- @branches << bran
- end
- end
- @branches.sort!
- rescue ScmCommandAborted
- nil
- end
-
- def tags
- return @tags if @tags
- cmd_args = %w|tag|
- git_cmd(cmd_args) do |io|
- @tags = io.readlines.sort!.map{|t| t.strip}
- end
- rescue ScmCommandAborted
- nil
- end
-
- def default_branch
- bras = self.branches
- return nil if bras.nil?
- default_bras = bras.select{|x| x.is_default == true}
- return default_bras.first.to_s if ! default_bras.empty?
- master_bras = bras.select{|x| x.to_s == 'master'}
- master_bras.empty? ? bras.first.to_s : 'master'
- end
-
- def entry(path=nil, identifier=nil)
- parts = path.to_s.split(%r{[\/\\]}).select {|n| !n.blank?}
- search_path = parts[0..-2].join('/')
- search_name = parts[-1]
- if search_path.blank? && search_name.blank?
- # Root entry
- Entry.new(:path => '', :kind => 'dir')
- else
- # Search for the entry in the parent directory
- es = entries(search_path, identifier,
- options = {:report_last_commit => false})
- es ? es.detect {|e| e.name == search_name} : nil
- end
- end
-
- def entries(path=nil, identifier=nil, options={})
- path ||= ''
- p = scm_iconv(@path_encoding, 'UTF-8', path)
- entries = Entries.new
- cmd_args = %w|ls-tree -l|
- cmd_args << "HEAD:#{p}" if identifier.nil?
- cmd_args << "#{identifier}:#{p}" if identifier
- git_cmd(cmd_args) do |io|
- io.each_line do |line|
- e = line.chomp.to_s
- if e =~ /^\d+\s+(\w+)\s+([0-9a-f]{40})\s+([0-9-]+)\t(.+)$/
- type = $1
- sha = $2
- size = $3
- name = $4
- if name.respond_to?(:force_encoding)
- name.force_encoding(@path_encoding)
- end
- full_path = p.empty? ? name : "#{p}/#{name}"
- n = scm_iconv('UTF-8', @path_encoding, name)
- full_p = scm_iconv('UTF-8', @path_encoding, full_path)
- entries << Entry.new({:name => n,
- :path => full_p,
- :kind => (type == "tree") ? 'dir' : 'file',
- :size => (type == "tree") ? nil : size,
- :lastrev => options[:report_last_commit] ?
- lastrev(full_path, identifier) : Revision.new
- }) unless entries.detect{|entry| entry.name == name}
- end
- end
- end
- entries.sort_by_name
- rescue ScmCommandAborted
- nil
- end
-
- def lastrev(path, rev)
- return nil if path.nil?
- cmd_args = %w|log --no-color --encoding=UTF-8 --date=iso --pretty=fuller --no-merges -n 1|
- cmd_args << rev if rev
- cmd_args << "--" << path unless path.empty?
- lines = []
- git_cmd(cmd_args) { |io| lines = io.readlines }
- begin
- id = lines[0].split[1]
- author = lines[1].match('Author:\s+(.*)$')[1]
- time = Time.parse(lines[4].match('CommitDate:\s+(.*)$')[1])
-
- Revision.new({
- :identifier => id,
- :scmid => id,
- :author => author,
- :time => time,
- :message => nil,
- :paths => nil
- })
- rescue NoMethodError => e
- logger.error("The revision '#{path}' has a wrong format")
- return nil
- end
- rescue ScmCommandAborted
- nil
- end
-
- def revisions(path, identifier_from, identifier_to, options={})
- revs = Revisions.new
- cmd_args = %w|log --no-color --encoding=UTF-8 --raw --date=iso --pretty=fuller --parents --stdin|
- cmd_args << "--reverse" if options[:reverse]
- cmd_args << "-n" << "#{options[:limit].to_i}" if options[:limit]
- cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) if path && !path.empty?
- revisions = []
- if identifier_from || identifier_to
- revisions << ""
- revisions[0] << "#{identifier_from}.." if identifier_from
- revisions[0] << "#{identifier_to}" if identifier_to
- else
- unless options[:includes].blank?
- revisions += options[:includes]
- end
- unless options[:excludes].blank?
- revisions += options[:excludes].map{|r| "^#{r}"}
- end
- end
-
- git_cmd(cmd_args, {:write_stdin => true}) do |io|
- io.binmode
- io.puts(revisions.join("\n"))
- io.close_write
- files=[]
- changeset = {}
- parsing_descr = 0 #0: not parsing desc or files, 1: parsing desc, 2: parsing files
-
- io.each_line do |line|
- if line =~ /^commit ([0-9a-f]{40})(( [0-9a-f]{40})*)$/
- key = "commit"
- value = $1
- parents_str = $2
- if (parsing_descr == 1 || parsing_descr == 2)
- parsing_descr = 0
- revision = Revision.new({
- :identifier => changeset[:commit],
- :scmid => changeset[:commit],
- :author => changeset[:author],
- :time => Time.parse(changeset[:date]),
- :message => changeset[:description],
- :paths => files,
- :parents => changeset[:parents]
- })
- if block_given?
- yield revision
- else
- revs << revision
- end
- changeset = {}
- files = []
- end
- changeset[:commit] = $1
- unless parents_str.nil? or parents_str == ""
- changeset[:parents] = parents_str.strip.split(' ')
- end
- elsif (parsing_descr == 0) && line =~ /^(\w+):\s*(.*)$/
- key = $1
- value = $2
- if key == "Author"
- changeset[:author] = value
- elsif key == "CommitDate"
- changeset[:date] = value
- end
- elsif (parsing_descr == 0) && line.chomp.to_s == ""
- parsing_descr = 1
- changeset[:description] = ""
- elsif (parsing_descr == 1 || parsing_descr == 2) \
- && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\t(.+)$/
- parsing_descr = 2
- fileaction = $1
- filepath = $2
- p = scm_iconv('UTF-8', @path_encoding, filepath)
- files << {:action => fileaction, :path => p}
- elsif (parsing_descr == 1 || parsing_descr == 2) \
- && line =~ /^:\d+\s+\d+\s+[0-9a-f.]+\s+[0-9a-f.]+\s+(\w)\d+\s+(\S+)\t(.+)$/
- parsing_descr = 2
- fileaction = $1
- filepath = $3
- p = scm_iconv('UTF-8', @path_encoding, filepath)
- files << {:action => fileaction, :path => p}
- elsif (parsing_descr == 1) && line.chomp.to_s == ""
- parsing_descr = 2
- elsif (parsing_descr == 1)
- changeset[:description] << line[4..-1]
- end
- end
-
- if changeset[:commit]
- revision = Revision.new({
- :identifier => changeset[:commit],
- :scmid => changeset[:commit],
- :author => changeset[:author],
- :time => Time.parse(changeset[:date]),
- :message => changeset[:description],
- :paths => files,
- :parents => changeset[:parents]
- })
- if block_given?
- yield revision
- else
- revs << revision
- end
- end
- end
- revs
- rescue ScmCommandAborted => e
- err_msg = "git log error: #{e.message}"
- logger.error(err_msg)
- if block_given?
- raise CommandFailed, err_msg
- else
- revs
- end
- end
-
- def diff(path, identifier_from, identifier_to=nil)
- path ||= ''
- cmd_args = []
- if identifier_to
- cmd_args << "diff" << "--no-color" << identifier_to << identifier_from
- else
- cmd_args << "show" << "--no-color" << identifier_from
- end
- cmd_args << "--" << scm_iconv(@path_encoding, 'UTF-8', path) unless path.empty?
- diff = []
- git_cmd(cmd_args) do |io|
- io.each_line do |line|
- diff << line
- end
- end
- diff
- rescue ScmCommandAborted
- nil
- end
-
- def annotate(path, identifier=nil)
- identifier = 'HEAD' if identifier.blank?
- cmd_args = %w|blame|
- cmd_args << "-p" << identifier << "--" << scm_iconv(@path_encoding, 'UTF-8', path)
- blame = Annotate.new
- content = nil
- git_cmd(cmd_args) { |io| io.binmode; content = io.read }
- # git annotates binary files
- return nil if content.is_binary_data?
- identifier = ''
- # git shows commit author on the first occurrence only
- authors_by_commit = {}
- content.split("\n").each do |line|
- if line =~ /^([0-9a-f]{39,40})\s.*/
- identifier = $1
- elsif line =~ /^author (.+)/
- authors_by_commit[identifier] = $1.strip
- elsif line =~ /^\t(.*)/
- blame.add_line($1, Revision.new(
- :identifier => identifier,
- :revision => identifier,
- :scmid => identifier,
- :author => authors_by_commit[identifier]
- ))
- identifier = ''
- author = ''
- end
- end
- blame
- rescue ScmCommandAborted
- nil
- end
-
- def cat(path, identifier=nil)
- if identifier.nil?
- identifier = 'HEAD'
- end
- cmd_args = %w|show --no-color|
- cmd_args << "#{identifier}:#{scm_iconv(@path_encoding, 'UTF-8', path)}"
- cat = nil
- git_cmd(cmd_args) do |io|
- io.binmode
- cat = io.read
- end
- cat
- rescue ScmCommandAborted
- nil
- end
-
- class Revision < Redmine::Scm::Adapters::Revision
- # Returns the readable identifier
- def format_identifier
- identifier[0,8]
- end
- end
-
- def git_cmd(args, options = {}, &block)
- repo_path = root_url || url
- full_args = ['--git-dir', repo_path]
- if self.class.client_version_above?([1, 7, 2])
- full_args << '-c' << 'core.quotepath=false'
- full_args << '-c' << 'log.decorate=no'
- end
- full_args += args
- ret = shellout(
- self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
- options,
- &block
- )
- if $? && $?.exitstatus != 0
- raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}"
- end
- ret
- end
- private :git_cmd
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl b/trustie2/lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl
deleted file mode 100644
index a2a324ba2..000000000
--- a/trustie2/lib/redmine/scm/adapters/mercurial/hg-template-1.0.tmpl
+++ /dev/null
@@ -1,12 +0,0 @@
-changeset = 'This template must be used with --debug option\n'
-changeset_quiet = 'This template must be used with --debug option\n'
-changeset_verbose = 'This template must be used with --debug option\n'
-changeset_debug = '\n{author|escape} \n{date|isodatesec} \n\n{file_mods}{file_adds}{file_dels}{file_copies} \n{desc|escape} \n\n{parents} \n \n\n'
-
-file_mod = '{file_mod|urlescape} \n'
-file_add = '{file_add|urlescape} \n'
-file_del = '{file_del|urlescape} \n'
-file_copy = '{name|urlescape} \n'
-parent = '{node|short} \n'
-header='\n\n\n'
-# footer=" "
diff --git a/trustie2/lib/redmine/scm/adapters/mercurial/redminehelper.py b/trustie2/lib/redmine/scm/adapters/mercurial/redminehelper.py
deleted file mode 100644
index bd82c0020..000000000
--- a/trustie2/lib/redmine/scm/adapters/mercurial/redminehelper.py
+++ /dev/null
@@ -1,220 +0,0 @@
-# redminehelper: Redmine helper extension for Mercurial
-#
-# Copyright 2010 Alessio Franceschelli (alefranz.net)
-# Copyright 2010-2011 Yuya Nishihara
-#
-# This software may be used and distributed according to the terms of the
-# GNU General Public License version 2 or any later version.
-"""helper commands for Redmine to reduce the number of hg calls
-
-To test this extension, please try::
-
- $ hg --config extensions.redminehelper=redminehelper.py rhsummary
-
-I/O encoding:
-
-:file path: urlencoded, raw string
-:tag name: utf-8
-:branch name: utf-8
-:node: 12-digits (short) hex string
-
-Output example of rhsummary::
-
-
-
-
-
-
-
- ...
-
-
-
-Output example of rhmanifest::
-
-
-
-
-
-
- ...
-
- ...
-
-
-
-"""
-import re, time, cgi, urllib
-from mercurial import cmdutil, commands, node, error, hg
-
-_x = cgi.escape
-_u = lambda s: cgi.escape(urllib.quote(s))
-
-def _tip(ui, repo):
- # see mercurial/commands.py:tip
- def tiprev():
- try:
- return len(repo) - 1
- except TypeError: # Mercurial < 1.1
- return repo.changelog.count() - 1
- tipctx = repo.changectx(tiprev())
- ui.write(' \n'
- % (tipctx.rev(), _x(node.short(tipctx.node()))))
-
-_SPECIAL_TAGS = ('tip',)
-
-def _tags(ui, repo):
- # see mercurial/commands.py:tags
- for t, n in reversed(repo.tagslist()):
- if t in _SPECIAL_TAGS:
- continue
- try:
- r = repo.changelog.rev(n)
- except error.LookupError:
- continue
- ui.write(' \n'
- % (r, _x(node.short(n)), _x(t)))
-
-def _branches(ui, repo):
- # see mercurial/commands.py:branches
- def iterbranches():
- for t, n in repo.branchtags().iteritems():
- yield t, n, repo.changelog.rev(n)
- def branchheads(branch):
- try:
- return repo.branchheads(branch, closed=False)
- except TypeError: # Mercurial < 1.2
- return repo.branchheads(branch)
- for t, n, r in sorted(iterbranches(), key=lambda e: e[2], reverse=True):
- if repo.lookup(r) in branchheads(t):
- ui.write(' \n'
- % (r, _x(node.short(n)), _x(t)))
-
-def _manifest(ui, repo, path, rev):
- ctx = repo.changectx(rev)
- ui.write('\n'
- % (ctx.rev(), _u(path)))
-
- known = set()
- pathprefix = (path.rstrip('/') + '/').lstrip('/')
- for f, n in sorted(ctx.manifest().iteritems(), key=lambda e: e[0]):
- if not f.startswith(pathprefix):
- continue
- name = re.sub(r'/.*', '/', f[len(pathprefix):])
- if name in known:
- continue
- known.add(name)
-
- if name.endswith('/'):
- ui.write(' \n'
- % _x(urllib.quote(name[:-1])))
- else:
- fctx = repo.filectx(f, fileid=n)
- tm, tzoffset = fctx.date()
- ui.write(' \n'
- % (_u(name), fctx.rev(), _x(node.short(fctx.node())),
- tm, fctx.size(), ))
-
- ui.write(' \n')
-
-def rhannotate(ui, repo, *pats, **opts):
- rev = urllib.unquote_plus(opts.pop('rev', None))
- opts['rev'] = rev
- return commands.annotate(ui, repo, *map(urllib.unquote_plus, pats), **opts)
-
-def rhcat(ui, repo, file1, *pats, **opts):
- rev = urllib.unquote_plus(opts.pop('rev', None))
- opts['rev'] = rev
- return commands.cat(ui, repo, urllib.unquote_plus(file1), *map(urllib.unquote_plus, pats), **opts)
-
-def rhdiff(ui, repo, *pats, **opts):
- """diff repository (or selected files)"""
- change = opts.pop('change', None)
- if change: # add -c option for Mercurial<1.1
- base = repo.changectx(change).parents()[0].rev()
- opts['rev'] = [str(base), change]
- opts['nodates'] = True
- return commands.diff(ui, repo, *map(urllib.unquote_plus, pats), **opts)
-
-def rhlog(ui, repo, *pats, **opts):
- rev = opts.pop('rev')
- bra0 = opts.pop('branch')
- from_rev = urllib.unquote_plus(opts.pop('from', None))
- to_rev = urllib.unquote_plus(opts.pop('to' , None))
- bra = urllib.unquote_plus(opts.pop('rhbranch', None))
- from_rev = from_rev.replace('"', '\\"')
- to_rev = to_rev.replace('"', '\\"')
- if hg.util.version() >= '1.6':
- opts['rev'] = ['"%s":"%s"' % (from_rev, to_rev)]
- else:
- opts['rev'] = ['%s:%s' % (from_rev, to_rev)]
- opts['branch'] = [bra]
- return commands.log(ui, repo, *map(urllib.unquote_plus, pats), **opts)
-
-def rhmanifest(ui, repo, path='', **opts):
- """output the sub-manifest of the specified directory"""
- ui.write('\n')
- ui.write('\n')
- ui.write('\n' % _u(repo.root))
- try:
- _manifest(ui, repo, urllib.unquote_plus(path), urllib.unquote_plus(opts.get('rev')))
- finally:
- ui.write(' \n')
- ui.write(' \n')
-
-def rhsummary(ui, repo, **opts):
- """output the summary of the repository"""
- ui.write('\n')
- ui.write('\n')
- ui.write('\n' % _u(repo.root))
- try:
- _tip(ui, repo)
- _tags(ui, repo)
- _branches(ui, repo)
- # TODO: bookmarks in core (Mercurial>=1.8)
- finally:
- ui.write(' \n')
- ui.write(' \n')
-
-cmdtable = {
- 'rhannotate': (rhannotate,
- [('r', 'rev', '', 'revision'),
- ('u', 'user', None, 'list the author (long with -v)'),
- ('n', 'number', None, 'list the revision number (default)'),
- ('c', 'changeset', None, 'list the changeset'),
- ],
- 'hg rhannotate [-r REV] [-u] [-n] [-c] FILE...'),
- 'rhcat': (rhcat,
- [('r', 'rev', '', 'revision')],
- 'hg rhcat ([-r REV] ...) FILE...'),
- 'rhdiff': (rhdiff,
- [('r', 'rev', [], 'revision'),
- ('c', 'change', '', 'change made by revision')],
- 'hg rhdiff ([-c REV] | [-r REV] ...) [FILE]...'),
- 'rhlog': (rhlog,
- [
- ('r', 'rev', [], 'show the specified revision'),
- ('b', 'branch', [],
- 'show changesets within the given named branch'),
- ('l', 'limit', '',
- 'limit number of changes displayed'),
- ('d', 'date', '',
- 'show revisions matching date spec'),
- ('u', 'user', [],
- 'revisions committed by user'),
- ('', 'from', '',
- ''),
- ('', 'to', '',
- ''),
- ('', 'rhbranch', '',
- ''),
- ('', 'template', '',
- 'display with template')],
- 'hg rhlog [OPTION]... [FILE]'),
- 'rhmanifest': (rhmanifest,
- [('r', 'rev', '', 'show the specified revision')],
- 'hg rhmanifest [-r REV] [PATH]'),
- 'rhsummary': (rhsummary, [], 'hg rhsummary'),
-}
diff --git a/trustie2/lib/redmine/scm/adapters/mercurial_adapter.rb b/trustie2/lib/redmine/scm/adapters/mercurial_adapter.rb
deleted file mode 100644
index a6bf959c0..000000000
--- a/trustie2/lib/redmine/scm/adapters/mercurial_adapter.rb
+++ /dev/null
@@ -1,341 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'redmine/scm/adapters/abstract_adapter'
-require 'cgi'
-
-module Redmine
- module Scm
- module Adapters
- class MercurialAdapter < AbstractAdapter
-
- # Mercurial executable name
- HG_BIN = Redmine::Configuration['scm_mercurial_command'] || "hg"
- HELPERS_DIR = File.dirname(__FILE__) + "/mercurial"
- HG_HELPER_EXT = "#{HELPERS_DIR}/redminehelper.py"
- TEMPLATE_NAME = "hg-template"
- TEMPLATE_EXTENSION = "tmpl"
-
- # raised if hg command exited with error, e.g. unknown revision.
- class HgCommandAborted < CommandFailed; end
-
- class << self
- def client_command
- @@bin ||= HG_BIN
- end
-
- def sq_bin
- @@sq_bin ||= shell_quote_command
- end
-
- def client_version
- @@client_version ||= (hgversion || [])
- end
-
- def client_available
- client_version_above?([1, 2])
- end
-
- def hgversion
- # The hg version is expressed either as a
- # release number (eg 0.9.5 or 1.0) or as a revision
- # id composed of 12 hexa characters.
- theversion = hgversion_from_command_line.dup
- if theversion.respond_to?(:force_encoding)
- theversion.force_encoding('ASCII-8BIT')
- end
- if m = theversion.match(%r{\A(.*?)((\d+\.)+\d+)})
- m[2].scan(%r{\d+}).collect(&:to_i)
- end
- end
-
- def hgversion_from_command_line
- shellout("#{sq_bin} --version") { |io| io.read }.to_s
- end
-
- def template_path
- @@template_path ||= template_path_for(client_version)
- end
-
- def template_path_for(version)
- "#{HELPERS_DIR}/#{TEMPLATE_NAME}-1.0.#{TEMPLATE_EXTENSION}"
- end
- end
-
- def initialize(url, root_url=nil, login=nil, password=nil, path_encoding=nil)
- super
- @path_encoding = path_encoding.blank? ? 'UTF-8' : path_encoding
- end
-
- def path_encoding
- @path_encoding
- end
-
- def info
- tip = summary['repository']['tip']
- Info.new(:root_url => CGI.unescape(summary['repository']['root']),
- :lastrev => Revision.new(:revision => tip['revision'],
- :scmid => tip['node']))
- # rescue HgCommandAborted
- rescue Exception => e
- logger.error "hg: error during getting info: #{e.message}"
- nil
- end
-
- def tags
- as_ary(summary['repository']['tag']).map { |e| e['name'] }
- end
-
- # Returns map of {'tag' => 'nodeid', ...}
- def tagmap
- alist = as_ary(summary['repository']['tag']).map do |e|
- e.values_at('name', 'node')
- end
- Hash[*alist.flatten]
- end
-
- def branches
- brs = []
- as_ary(summary['repository']['branch']).each do |e|
- br = Branch.new(e['name'])
- br.revision = e['revision']
- br.scmid = e['node']
- brs << br
- end
- brs
- end
-
- # Returns map of {'branch' => 'nodeid', ...}
- def branchmap
- alist = as_ary(summary['repository']['branch']).map do |e|
- e.values_at('name', 'node')
- end
- Hash[*alist.flatten]
- end
-
- def summary
- return @summary if @summary
- hg 'rhsummary' do |io|
- output = io.read
- if output.respond_to?(:force_encoding)
- output.force_encoding('UTF-8')
- end
- begin
- @summary = parse_xml(output)['rhsummary']
- rescue
- end
- end
- end
- private :summary
-
- def entries(path=nil, identifier=nil, options={})
- p1 = scm_iconv(@path_encoding, 'UTF-8', path)
- manifest = hg('rhmanifest', '-r', CGI.escape(hgrev(identifier)),
- CGI.escape(without_leading_slash(p1.to_s))) do |io|
- output = io.read
- if output.respond_to?(:force_encoding)
- output.force_encoding('UTF-8')
- end
- begin
- parse_xml(output)['rhmanifest']['repository']['manifest']
- rescue
- end
- end
- path_prefix = path.blank? ? '' : with_trailling_slash(path)
-
- entries = Entries.new
- as_ary(manifest['dir']).each do |e|
- n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name']))
- p = "#{path_prefix}#{n}"
- entries << Entry.new(:name => n, :path => p, :kind => 'dir')
- end
-
- as_ary(manifest['file']).each do |e|
- n = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['name']))
- p = "#{path_prefix}#{n}"
- lr = Revision.new(:revision => e['revision'], :scmid => e['node'],
- :identifier => e['node'],
- :time => Time.at(e['time'].to_i))
- entries << Entry.new(:name => n, :path => p, :kind => 'file',
- :size => e['size'].to_i, :lastrev => lr)
- end
-
- entries
- rescue HgCommandAborted
- nil # means not found
- end
-
- def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
- revs = Revisions.new
- each_revision(path, identifier_from, identifier_to, options) { |e| revs << e }
- revs
- end
-
- # Iterates the revisions by using a template file that
- # makes Mercurial produce a xml output.
- def each_revision(path=nil, identifier_from=nil, identifier_to=nil, options={})
- hg_args = ['log', '--debug', '-C', '--style', self.class.template_path]
- hg_args << '-r' << "#{hgrev(identifier_from)}:#{hgrev(identifier_to)}"
- hg_args << '--limit' << options[:limit] if options[:limit]
- hg_args << hgtarget(path) unless path.blank?
- log = hg(*hg_args) do |io|
- output = io.read
- if output.respond_to?(:force_encoding)
- output.force_encoding('UTF-8')
- end
- begin
- # Mercurial < 1.5 does not support footer template for ''
- parse_xml("#{output}")['log']
- rescue
- end
- end
- as_ary(log['logentry']).each do |le|
- cpalist = as_ary(le['paths']['path-copied']).map do |e|
- [e['__content__'], e['copyfrom-path']].map do |s|
- scm_iconv('UTF-8', @path_encoding, CGI.unescape(s))
- end
- end
- cpmap = Hash[*cpalist.flatten]
- paths = as_ary(le['paths']['path']).map do |e|
- p = scm_iconv('UTF-8', @path_encoding, CGI.unescape(e['__content__']) )
- {:action => e['action'],
- :path => with_leading_slash(p),
- :from_path => (cpmap.member?(p) ? with_leading_slash(cpmap[p]) : nil),
- :from_revision => (cpmap.member?(p) ? le['node'] : nil)}
- end.sort { |a, b| a[:path] <=> b[:path] }
- parents_ary = []
- as_ary(le['parents']['parent']).map do |par|
- parents_ary << par['__content__'] if par['__content__'] != "000000000000"
- end
- yield Revision.new(:revision => le['revision'],
- :scmid => le['node'],
- :author => (le['author']['__content__'] rescue ''),
- :time => Time.parse(le['date']['__content__']),
- :message => le['msg']['__content__'],
- :paths => paths,
- :parents => parents_ary)
- end
- self
- end
-
- # Returns list of nodes in the specified branch
- def nodes_in_branch(branch, options={})
- hg_args = ['rhlog', '--template', '{node|short}\n', '--rhbranch', CGI.escape(branch)]
- hg_args << '--from' << CGI.escape(branch)
- hg_args << '--to' << '0'
- hg_args << '--limit' << options[:limit] if options[:limit]
- hg(*hg_args) { |io| io.readlines.map { |e| e.chomp } }
- end
-
- def diff(path, identifier_from, identifier_to=nil)
- hg_args = %w|rhdiff|
- if identifier_to
- hg_args << '-r' << hgrev(identifier_to) << '-r' << hgrev(identifier_from)
- else
- hg_args << '-c' << hgrev(identifier_from)
- end
- unless path.blank?
- p = scm_iconv(@path_encoding, 'UTF-8', path)
- hg_args << CGI.escape(hgtarget(p))
- end
- diff = []
- hg *hg_args do |io|
- io.each_line do |line|
- diff << line
- end
- end
- diff
- rescue HgCommandAborted
- nil # means not found
- end
-
- def cat(path, identifier=nil)
- p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path))
- hg 'rhcat', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
- io.binmode
- io.read
- end
- rescue HgCommandAborted
- nil # means not found
- end
-
- def annotate(path, identifier=nil)
- p = CGI.escape(scm_iconv(@path_encoding, 'UTF-8', path))
- blame = Annotate.new
- hg 'rhannotate', '-ncu', '-r', CGI.escape(hgrev(identifier)), hgtarget(p) do |io|
- io.each_line do |line|
- line.force_encoding('ASCII-8BIT') if line.respond_to?(:force_encoding)
- next unless line =~ %r{^([^:]+)\s(\d+)\s([0-9a-f]+):\s(.*)$}
- r = Revision.new(:author => $1.strip, :revision => $2, :scmid => $3,
- :identifier => $3)
- blame.add_line($4.rstrip, r)
- end
- end
- blame
- rescue HgCommandAborted
- # means not found or cannot be annotated
- Annotate.new
- end
-
- class Revision < Redmine::Scm::Adapters::Revision
- # Returns the readable identifier
- def format_identifier
- "#{revision}:#{scmid}"
- end
- end
-
- # Runs 'hg' command with the given args
- def hg(*args, &block)
- repo_path = root_url || url
- full_args = ['-R', repo_path, '--encoding', 'utf-8']
- full_args << '--config' << "extensions.redminehelper=#{HG_HELPER_EXT}"
- full_args << '--config' << 'diff.git=false'
- full_args += args
- ret = shellout(
- self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' '),
- &block
- )
- if $? && $?.exitstatus != 0
- raise HgCommandAborted, "hg exited with non-zero status: #{$?.exitstatus}"
- end
- ret
- end
- private :hg
-
- # Returns correct revision identifier
- def hgrev(identifier, sq=false)
- rev = identifier.blank? ? 'tip' : identifier.to_s
- rev = shell_quote(rev) if sq
- rev
- end
- private :hgrev
-
- def hgtarget(path)
- path ||= ''
- root_url + '/' + without_leading_slash(path)
- end
- private :hgtarget
-
- def as_ary(o)
- return [] unless o
- o.is_a?(Array) ? o : Array[o]
- end
- private :as_ary
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/scm/adapters/subversion_adapter.rb b/trustie2/lib/redmine/scm/adapters/subversion_adapter.rb
deleted file mode 100644
index c496ba148..000000000
--- a/trustie2/lib/redmine/scm/adapters/subversion_adapter.rb
+++ /dev/null
@@ -1,291 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'redmine/scm/adapters/abstract_adapter'
-require 'uri'
-
-module Redmine
- module Scm
- module Adapters
- class SubversionAdapter < AbstractAdapter
-
- # SVN executable name
- SVN_BIN = Redmine::Configuration['scm_subversion_command'] || "svn"
-
- class << self
- def client_command
- @@bin ||= SVN_BIN
- end
-
- def sq_bin
- @@sq_bin ||= shell_quote_command
- end
-
- def client_version
- @@client_version ||= (svn_binary_version || [])
- end
-
- def client_available
- # --xml options are introduced in 1.3.
- # http://subversion.apache.org/docs/release-notes/1.3.html
- client_version_above?([1, 3])
- end
-
- def svn_binary_version
- scm_version = scm_version_from_command_line.dup
- if scm_version.respond_to?(:force_encoding)
- scm_version.force_encoding('ASCII-8BIT')
- end
- if m = scm_version.match(%r{\A(.*?)((\d+\.)+\d+)})
- m[2].scan(%r{\d+}).collect(&:to_i)
- end
- end
-
- def scm_version_from_command_line
- shellout("#{sq_bin} --version") { |io| io.read }.to_s
- end
- end
-
- # Get info about the svn repository
- def info
- cmd = "#{self.class.sq_bin} info --xml #{target}"
- cmd << credentials_string
- info = nil
- shellout(cmd) do |io|
- output = io.read
- if output.respond_to?(:force_encoding)
- output.force_encoding('UTF-8')
- end
- begin
- doc = parse_xml(output)
- # root_url = doc.elements["info/entry/repository/root"].text
- info = Info.new({:root_url => doc['info']['entry']['repository']['root']['__content__'],
- :lastrev => Revision.new({
- :identifier => doc['info']['entry']['commit']['revision'],
- :time => Time.parse(doc['info']['entry']['commit']['date']['__content__']).localtime,
- :author => (doc['info']['entry']['commit']['author'] ? doc['info']['entry']['commit']['author']['__content__'] : "")
- })
- })
- rescue
- end
- end
- return nil if $? && $?.exitstatus != 0
- info
- rescue CommandFailed
- return nil
- end
-
- # Returns an Entries collection
- # or nil if the given path doesn't exist in the repository
- def entries(path=nil, identifier=nil, options={})
- path ||= ''
- identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
- entries = Entries.new
- cmd = "#{self.class.sq_bin} list --xml #{target(path)}@#{identifier}"
- cmd << credentials_string
- shellout(cmd) do |io|
- output = io.read
- if output.respond_to?(:force_encoding)
- output.force_encoding('UTF-8')
- end
- begin
- doc = parse_xml(output)
- each_xml_element(doc['lists']['list'], 'entry') do |entry|
- commit = entry['commit']
- commit_date = commit['date']
- # Skip directory if there is no commit date (usually that
- # means that we don't have read access to it)
- next if entry['kind'] == 'dir' && commit_date.nil?
- name = entry['name']['__content__']
- entries << Entry.new({:name => URI.unescape(name),
- :path => ((path.empty? ? "" : "#{path}/") + name),
- :kind => entry['kind'],
- :size => ((s = entry['size']) ? s['__content__'].to_i : nil),
- :lastrev => Revision.new({
- :identifier => commit['revision'],
- :time => Time.parse(commit_date['__content__'].to_s).localtime,
- :author => ((a = commit['author']) ? a['__content__'] : nil)
- })
- })
- end
- rescue Exception => e
- logger.error("Error parsing svn output: #{e.message}")
- logger.error("Output was:\n #{output}")
- end
- end
- return nil if $? && $?.exitstatus != 0
- logger.debug("Found #{entries.size} entries in the repository for #{target(path)}") if logger && logger.debug?
- entries.sort_by_name
- end
-
- def properties(path, identifier=nil)
- # proplist xml output supported in svn 1.5.0 and higher
- return nil unless self.class.client_version_above?([1, 5, 0])
-
- identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
- cmd = "#{self.class.sq_bin} proplist --verbose --xml #{target(path)}@#{identifier}"
- cmd << credentials_string
- properties = {}
- shellout(cmd) do |io|
- output = io.read
- if output.respond_to?(:force_encoding)
- output.force_encoding('UTF-8')
- end
- begin
- doc = parse_xml(output)
- each_xml_element(doc['properties']['target'], 'property') do |property|
- properties[ property['name'] ] = property['__content__'].to_s
- end
- rescue
- end
- end
- return nil if $? && $?.exitstatus != 0
- properties
- end
-
- def revisions(path=nil, identifier_from=nil, identifier_to=nil, options={})
- path ||= ''
- identifier_from = (identifier_from && identifier_from.to_i > 0) ? identifier_from.to_i : "HEAD"
- identifier_to = (identifier_to && identifier_to.to_i > 0) ? identifier_to.to_i : 1
- revisions = Revisions.new
- cmd = "#{self.class.sq_bin} log --xml -r #{identifier_from}:#{identifier_to}"
- cmd << credentials_string
- cmd << " --verbose " if options[:with_paths]
- cmd << " --limit #{options[:limit].to_i}" if options[:limit]
- cmd << ' ' + target(path)
- shellout(cmd) do |io|
- output = io.read
- if output.respond_to?(:force_encoding)
- output.force_encoding('UTF-8')
- end
- begin
- doc = parse_xml(output)
- each_xml_element(doc['log'], 'logentry') do |logentry|
- paths = []
- each_xml_element(logentry['paths'], 'path') do |path|
- paths << {:action => path['action'],
- :path => path['__content__'],
- :from_path => path['copyfrom-path'],
- :from_revision => path['copyfrom-rev']
- }
- end if logentry['paths'] && logentry['paths']['path']
- paths.sort! { |x,y| x[:path] <=> y[:path] }
-
- revisions << Revision.new({:identifier => logentry['revision'],
- :author => (logentry['author'] ? logentry['author']['__content__'] : ""),
- :time => Time.parse(logentry['date']['__content__'].to_s).localtime,
- :message => logentry['msg']['__content__'],
- :paths => paths
- })
- end
- rescue
- end
- end
- return nil if $? && $?.exitstatus != 0
- revisions
- end
-
- def diff(path, identifier_from, identifier_to=nil)
- path ||= ''
- identifier_from = (identifier_from and identifier_from.to_i > 0) ? identifier_from.to_i : ''
-
- identifier_to = (identifier_to and identifier_to.to_i > 0) ? identifier_to.to_i : (identifier_from.to_i - 1)
-
- cmd = "#{self.class.sq_bin} diff -r "
- cmd << "#{identifier_to}:"
- cmd << "#{identifier_from}"
- cmd << " #{target(path)}@#{identifier_from}"
- cmd << credentials_string
- diff = []
- shellout(cmd) do |io|
- io.each_line do |line|
- diff << line
- end
- end
- return nil if $? && $?.exitstatus != 0
- diff
- end
-
- def cat(path, identifier=nil)
- identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
- cmd = "#{self.class.sq_bin} cat #{target(path)}@#{identifier}"
- cmd << credentials_string
- cat = nil
- shellout(cmd) do |io|
- io.binmode
- cat = io.read
- end
- return nil if $? && $?.exitstatus != 0
- cat
- end
-
- def annotate(path, identifier=nil)
- identifier = (identifier and identifier.to_i > 0) ? identifier.to_i : "HEAD"
- cmd = "#{self.class.sq_bin} blame #{target(path)}@#{identifier}"
- cmd << credentials_string
- blame = Annotate.new
- shellout(cmd) do |io|
- io.each_line do |line|
- next unless line =~ %r{^\s*(\d+)\s*(\S+)\s(.*)$}
- rev = $1
- blame.add_line($3.rstrip,
- Revision.new(
- :identifier => rev,
- :revision => rev,
- :author => $2.strip
- ))
- end
- end
- return nil if $? && $?.exitstatus != 0
- blame
- end
-
- private
-
- def credentials_string
- str = ''
- str << " --username #{shell_quote(@login)}" unless @login.blank?
- str << " --password #{shell_quote(@password)}" unless @login.blank? || @password.blank?
- str << " --no-auth-cache --non-interactive"
- str
- end
-
- # Helper that iterates over the child elements of a xml node
- # MiniXml returns a hash when a single child is found
- # or an array of hashes for multiple children
- def each_xml_element(node, name)
- if node && node[name]
- if node[name].is_a?(Hash)
- yield node[name]
- else
- node[name].each do |element|
- yield element
- end
- end
- end
- end
-
- def target(path = '')
- base = path.match(/^\//) ? root_url : url
- uri = "#{base}/#{path}"
- uri = URI.escape(URI.escape(uri), '[]')
- shell_quote(uri.gsub(/[?<>\*]/, ''))
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/scm/base.rb b/trustie2/lib/redmine/scm/base.rb
deleted file mode 100644
index b33a9cfd1..000000000
--- a/trustie2/lib/redmine/scm/base.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-module Redmine
- module Scm
- class Base
- class << self
-
- def all
- @scms || []
- end
-
- # Add a new SCM adapter and repository
- def add(scm_name)
- @scms ||= []
- @scms << scm_name
- end
-
- # Remove a SCM adapter from Redmine's list of supported scms
- def delete(scm_name)
- @scms.delete(scm_name)
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/search.rb b/trustie2/lib/redmine/search.rb
deleted file mode 100644
index dc2e526e0..000000000
--- a/trustie2/lib/redmine/search.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Search
-
- mattr_accessor :available_search_types
-
- @@available_search_types = []
-
- class << self
- def map(&block)
- yield self
- end
-
- # Registers a search provider
- def register(search_type, options={})
- search_type = search_type.to_s
- @@available_search_types << search_type unless @@available_search_types.include?(search_type)
- end
- end
-
- module Controller
- def self.included(base)
- base.extend(ClassMethods)
- end
-
- module ClassMethods
- @@default_search_scopes = Hash.new {|hash, key| hash[key] = {:default => nil, :actions => {}}}
- mattr_accessor :default_search_scopes
-
- # Set the default search scope for a controller or specific actions
- # Examples:
- # * search_scope :issues # => sets the search scope to :issues for the whole controller
- # * search_scope :issues, :only => :index
- # * search_scope :issues, :only => [:index, :show]
- def default_search_scope(id, options = {})
- if actions = options[:only]
- actions = [] << actions unless actions.is_a?(Array)
- actions.each {|a| default_search_scopes[controller_name.to_sym][:actions][a.to_sym] = id.to_s}
- else
- default_search_scopes[controller_name.to_sym][:default] = id.to_s
- end
- end
- end
-
- def default_search_scopes
- self.class.default_search_scopes
- end
-
- # Returns the default search scope according to the current action
- def default_search_scope
- @default_search_scope ||= default_search_scopes[controller_name.to_sym][:actions][action_name.to_sym] ||
- default_search_scopes[controller_name.to_sym][:default]
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/subclass_factory.rb b/trustie2/lib/redmine/subclass_factory.rb
deleted file mode 100644
index 378bd39bc..000000000
--- a/trustie2/lib/redmine/subclass_factory.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 SubclassFactory
- def self.included(base)
- base.extend ClassMethods
- end
-
- module ClassMethods
- def get_subclass(class_name)
- klass = nil
- begin
- klass = class_name.to_s.classify.constantize
- rescue
- # invalid class name
- end
- unless subclasses.include? klass
- klass = nil
- end
- klass
- end
-
- # Returns an instance of the given subclass name
- def new_subclass_instance(class_name, *args)
- klass = get_subclass(class_name)
- if klass
- klass.new(*args)
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/syntax_highlighting.rb b/trustie2/lib/redmine/syntax_highlighting.rb
deleted file mode 100644
index e8d9067d4..000000000
--- a/trustie2/lib/redmine/syntax_highlighting.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 SyntaxHighlighting
-
- class << self
- attr_reader :highlighter
- delegate :highlight_by_filename, :highlight_by_language, :to => :highlighter
-
- def highlighter=(name)
- if name.is_a?(Module)
- @highlighter = name
- else
- @highlighter = const_get(name)
- end
- end
- end
-
- module CodeRay
- require 'coderay'
- require 'coderay/helpers/file_type'
-
- class << self
- # Highlights +text+ as the content of +filename+
- # Should not return line numbers nor outer pre tag
- def highlight_by_filename(text, filename)
- language = ::CodeRay::FileType[filename]
- language ? ::CodeRay.scan(text, language).html(:break_lines => true) : ERB::Util.h(text)
- end
-
- # Highlights +text+ using +language+ syntax
- # Should not return outer pre tag
- def highlight_by_language(text, language)
- ::CodeRay.scan(text, language).html(:wrap => :span)
- end
- end
- end
- end
-
- SyntaxHighlighting.highlighter = 'CodeRay'
-end
diff --git a/trustie2/lib/redmine/themes.rb b/trustie2/lib/redmine/themes.rb
deleted file mode 100644
index eb2ba9151..000000000
--- a/trustie2/lib/redmine/themes.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Themes
-
- # Return an array of installed themes
- def self.themes
- @@installed_themes ||= scan_themes
- end
-
- # Rescan themes directory
- def self.rescan
- @@installed_themes = scan_themes
- end
-
- # Return theme for given id, or nil if it's not found
- def self.theme(id, options={})
- return nil if id.blank?
-
- found = themes.find {|t| t.id == id}
- if found.nil? && options[:rescan] != false
- rescan
- found = theme(id, :rescan => false)
- end
- found
- end
-
- # Class used to represent a theme
- class Theme
- attr_reader :path, :name, :dir
-
- def initialize(path)
- @path = path
- @dir = File.basename(path)
- @name = @dir.humanize
- @stylesheets = nil
- @javascripts = nil
- end
-
- # Directory name used as the theme id
- def id; dir end
-
- def ==(theme)
- theme.is_a?(Theme) && theme.dir == dir
- end
-
- def <=>(theme)
- name <=> theme.name
- end
-
- def stylesheets
- @stylesheets ||= assets("stylesheets", "css")
- end
-
- def images
- @images ||= assets("images")
- end
-
- def javascripts
- @javascripts ||= assets("javascripts", "js")
- end
-
- def stylesheet_path(source)
- "/themes/#{dir}/stylesheets/#{source}"
- end
-
- def image_path(source)
- "/themes/#{dir}/images/#{source}"
- end
-
- def javascript_path(source)
- "/themes/#{dir}/javascripts/#{source}"
- end
-
- private
-
- def assets(dir, ext=nil)
- if ext
- Dir.glob("#{path}/#{dir}/*.#{ext}").collect {|f| File.basename(f).gsub(/\.#{ext}$/, '')}
- else
- Dir.glob("#{path}/#{dir}/*").collect {|f| File.basename(f)}
- end
- end
- end
-
- private
-
- def self.scan_themes
- dirs = Dir.glob("#{Rails.public_path}/themes/*").select do |f|
- # A theme should at least override application.css
- File.directory?(f) && File.exist?("#{f}/stylesheets/application.css")
- end
- dirs.collect {|dir| Theme.new(dir)}.sort
- end
- end
-end
-
-module ApplicationHelper
- def current_theme
- unless instance_variable_defined?(:@current_theme)
- @current_theme = Redmine::Themes.theme(Setting.ui_theme)
- end
- @current_theme
- end
-
- # Returns the header tags for the current theme
- def heads_for_theme
- if current_theme && current_theme.javascripts.include?('theme')
- javascript_include_tag current_theme.javascript_path('theme')
- end
- end
-end
diff --git a/trustie2/lib/redmine/thumbnail.rb b/trustie2/lib/redmine/thumbnail.rb
deleted file mode 100644
index 96f9dfa3e..000000000
--- a/trustie2/lib/redmine/thumbnail.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'fileutils'
-
-module Redmine
- module Thumbnail
- extend Redmine::Utils::Shell
-
- CONVERT_BIN = (Redmine::Configuration['imagemagick_convert_command'] || 'convert').freeze
-
- # Generates a thumbnail for the source image to target
- def self.generate(source, target, size)
- return nil unless convert_available?
- unless File.exists?(target)
- directory = File.dirname(target)
- unless File.exists?(directory)
- FileUtils.mkdir_p directory
- end
- size_option = "#{size}x#{size}>"
- cmd = "#{shell_quote CONVERT_BIN} #{shell_quote source} -thumbnail #{shell_quote size_option} #{shell_quote target}"
- unless system(cmd)
- logger.error("Creating thumbnail failed (#{$?}):\nCommand: #{cmd}")
- return nil
- end
- end
- target
- end
-
- def self.convert_available?
- return @convert_available if defined?(@convert_available)
- @convert_available = system("#{shell_quote CONVERT_BIN} -version") rescue false
- logger.warn("Imagemagick's convert binary (#{CONVERT_BIN}) not available") unless @convert_available
- @convert_available
- end
-
- def self.logger
- Rails.logger
- end
- end
-end
diff --git a/trustie2/lib/redmine/unified_diff.rb b/trustie2/lib/redmine/unified_diff.rb
deleted file mode 100644
index 548003220..000000000
--- a/trustie2/lib/redmine/unified_diff.rb
+++ /dev/null
@@ -1,294 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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
- # Class used to parse unified diffs
- class UnifiedDiff < Array
- attr_reader :diff_type, :diff_style
-
- def initialize(diff, options={})
- options.assert_valid_keys(:type, :style, :max_lines)
- diff = diff.split("\n") if diff.is_a?(String)
- @diff_type = options[:type] || 'inline'
- @diff_style = options[:style]
- lines = 0
- @truncated = false
- diff_table = DiffTable.new(diff_type, diff_style)
- diff.each do |line_raw|
- line = Redmine::CodesetUtil.to_utf8_by_setting(line_raw)
- unless diff_table.add_line(line)
- self << diff_table if diff_table.length > 0
- diff_table = DiffTable.new(diff_type, diff_style)
- end
- lines += 1
- if options[:max_lines] && lines > options[:max_lines]
- @truncated = true
- break
- end
- end
- self << diff_table unless diff_table.empty?
- self
- end
-
- def truncated?; @truncated; end
- end
-
- # Class that represents a file diff
- class DiffTable < Array
- attr_reader :file_name
-
- # Initialize with a Diff file and the type of Diff View
- # The type view must be inline or sbs (side_by_side)
- def initialize(type="inline", style=nil)
- @parsing = false
- @added = 0
- @removed = 0
- @type = type
- @style = style
- @file_name = nil
- @git_diff = false
- end
-
- # Function for add a line of this Diff
- # Returns false when the diff ends
- def add_line(line)
- unless @parsing
- if line =~ /^(---|\+\+\+) (.*)$/
- self.file_name = $2
- elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
- @line_num_l = $2.to_i
- @line_num_r = $5.to_i
- @parsing = true
- end
- else
- if line =~ %r{^[^\+\-\s@\\]}
- @parsing = false
- return false
- elsif line =~ /^@@ (\+|\-)(\d+)(,\d+)? (\+|\-)(\d+)(,\d+)? @@/
- @line_num_l = $2.to_i
- @line_num_r = $5.to_i
- else
- parse_line(line, @type)
- end
- end
- return true
- end
-
- def each_line
- prev_line_left, prev_line_right = nil, nil
- each do |line|
- spacing = prev_line_left && prev_line_right && (line.nb_line_left != prev_line_left+1) && (line.nb_line_right != prev_line_right+1)
- yield spacing, line
- prev_line_left = line.nb_line_left.to_i if line.nb_line_left.to_i > 0
- prev_line_right = line.nb_line_right.to_i if line.nb_line_right.to_i > 0
- end
- end
-
- def inspect
- puts '### DIFF TABLE ###'
- puts "file : #{file_name}"
- self.each do |d|
- d.inspect
- end
- end
-
- private
-
- def file_name=(arg)
- both_git_diff = false
- if file_name.nil?
- @git_diff = true if arg =~ %r{^(a/|/dev/null)}
- else
- both_git_diff = (@git_diff && arg =~ %r{^(b/|/dev/null)})
- end
- if both_git_diff
- if file_name && arg == "/dev/null"
- # keep the original file name
- @file_name = file_name.sub(%r{^a/}, '')
- else
- # remove leading b/
- @file_name = arg.sub(%r{^b/}, '')
- end
- elsif @style == "Subversion"
- # removing trailing "(revision nn)"
- @file_name = arg.sub(%r{\t+\(.*\)$}, '')
- else
- @file_name = arg
- end
- end
-
- def diff_for_added_line
- if @type == 'sbs' && @removed > 0 && @added < @removed
- self[-(@removed - @added)]
- else
- diff = Diff.new
- self << diff
- diff
- end
- end
-
- def parse_line(line, type="inline")
- if line[0, 1] == "+"
- diff = diff_for_added_line
- diff.line_right = line[1..-1]
- diff.nb_line_right = @line_num_r
- diff.type_diff_right = 'diff_in'
- @line_num_r += 1
- @added += 1
- true
- elsif line[0, 1] == "-"
- diff = Diff.new
- diff.line_left = line[1..-1]
- diff.nb_line_left = @line_num_l
- diff.type_diff_left = 'diff_out'
- self << diff
- @line_num_l += 1
- @removed += 1
- true
- else
- write_offsets
- if line[0, 1] =~ /\s/
- diff = Diff.new
- diff.line_right = line[1..-1]
- diff.nb_line_right = @line_num_r
- diff.line_left = line[1..-1]
- diff.nb_line_left = @line_num_l
- self << diff
- @line_num_l += 1
- @line_num_r += 1
- true
- elsif line[0, 1] = "\\"
- true
- else
- false
- end
- end
- end
-
- def write_offsets
- if @added > 0 && @added == @removed
- @added.times do |i|
- line = self[-(1 + i)]
- removed = (@type == 'sbs') ? line : self[-(1 + @added + i)]
- offsets = offsets(removed.line_left, line.line_right)
- removed.offsets = line.offsets = offsets
- end
- end
- @added = 0
- @removed = 0
- end
-
- def offsets(line_left, line_right)
- if line_left.present? && line_right.present? && line_left != line_right
- max = [line_left.size, line_right.size].min
- starting = 0
- while starting < max && line_left[starting] == line_right[starting]
- starting += 1
- end
- if (! "".respond_to?(:force_encoding)) && starting < line_left.size
- while line_left[starting].ord.between?(128, 191) && starting > 0
- starting -= 1
- end
- end
- ending = -1
- while ending >= -(max - starting) && line_left[ending] == line_right[ending]
- ending -= 1
- end
- if (! "".respond_to?(:force_encoding)) && ending > (-1 * line_left.size)
- while line_left[ending].ord.between?(128, 191) && ending > -1
- ending -= 1
- end
- end
- unless starting == 0 && ending == -1
- [starting, ending]
- end
- end
- end
- end
-
- # A line of diff
- class Diff
- attr_accessor :nb_line_left
- attr_accessor :line_left
- attr_accessor :nb_line_right
- attr_accessor :line_right
- attr_accessor :type_diff_right
- attr_accessor :type_diff_left
- attr_accessor :offsets
-
- def initialize()
- self.nb_line_left = ''
- self.nb_line_right = ''
- self.line_left = ''
- self.line_right = ''
- self.type_diff_right = ''
- self.type_diff_left = ''
- end
-
- def type_diff
- type_diff_right == 'diff_in' ? type_diff_right : type_diff_left
- end
-
- def line
- type_diff_right == 'diff_in' ? line_right : line_left
- end
-
- def html_line_left
- line_to_html(line_left, offsets)
- end
-
- def html_line_right
- line_to_html(line_right, offsets)
- end
-
- def html_line
- line_to_html(line, offsets)
- end
-
- def inspect
- puts '### Start Line Diff ###'
- puts self.nb_line_left
- puts self.line_left
- puts self.nb_line_right
- puts self.line_right
- end
-
- private
-
- def line_to_html(line, offsets)
- html = line_to_html_raw(line, offsets)
- html.force_encoding('UTF-8') if html.respond_to?(:force_encoding)
- html
- end
-
- def line_to_html_raw(line, offsets)
- if offsets
- s = ''
- unless offsets.first == 0
- s << CGI.escapeHTML(line[0..offsets.first-1])
- end
- s << '' + CGI.escapeHTML(line[offsets.first..offsets.last]) + ''
- unless offsets.last == -1
- s << CGI.escapeHTML(line[offsets.last+1..-1])
- end
- s
- else
- CGI.escapeHTML(line)
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/utils.rb b/trustie2/lib/redmine/utils.rb
deleted file mode 100644
index c289404cb..000000000
--- a/trustie2/lib/redmine/utils.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Utils
- class << self
- # Returns the relative root url of the application
- def relative_url_root
- ActionController::Base.respond_to?('relative_url_root') ?
- ActionController::Base.relative_url_root.to_s :
- ActionController::Base.config.relative_url_root.to_s
- end
-
- # Sets the relative root url of the application
- def relative_url_root=(arg)
- if ActionController::Base.respond_to?('relative_url_root=')
- ActionController::Base.relative_url_root=arg
- else
- ActionController::Base.config.relative_url_root = arg
- end
- end
-
- # Generates a n bytes random hex string
- # Example:
- # random_hex(4) # => "89b8c729"
- def random_hex(n)
- SecureRandom.hex(n)
- end
- end
-
- module Shell
- def shell_quote(str)
- if Redmine::Platform.mswin?
- '"' + str.gsub(/"/, '\\"') + '"'
- else
- "'" + str.gsub(/'/, "'\"'\"'") + "'"
- end
- end
- end
-
- module DateCalculation
- # Returns the number of working days between from and to
- def working_days(from, to)
- days = (to - from).to_i
- if days > 0
- weeks = days / 7
- result = weeks * (7 - non_working_week_days.size)
- days_left = days - weeks * 7
- start_cwday = from.cwday
- days_left.times do |i|
- unless non_working_week_days.include?(((start_cwday + i - 1) % 7) + 1)
- result += 1
- end
- end
- result
- else
- 0
- end
- end
-
- # Adds working days to the given date
- def add_working_days(date, working_days)
- if working_days > 0
- weeks = working_days / (7 - non_working_week_days.size)
- result = weeks * 7
- days_left = working_days - weeks * (7 - non_working_week_days.size)
- cwday = date.cwday
- while days_left > 0
- cwday += 1
- unless non_working_week_days.include?(((cwday - 1) % 7) + 1)
- days_left -= 1
- end
- result += 1
- end
- next_working_date(date + result)
- else
- date
- end
- end
-
- # Returns the date of the first day on or after the given date that is a working day
- def next_working_date(date)
- cwday = date.cwday
- days = 0
- while non_working_week_days.include?(((cwday + days - 1) % 7) + 1)
- days += 1
- end
- date + days
- end
-
- # Returns the index of non working week days (1=monday, 7=sunday)
- def non_working_week_days
- @non_working_week_days ||= begin
- days = Setting.non_working_week_days
- if days.is_a?(Array) && days.size < 7
- days.map(&:to_i)
- else
- []
- end
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/version.rb b/trustie2/lib/redmine/version.rb
deleted file mode 100644
index d7e9c5fa4..000000000
--- a/trustie2/lib/redmine/version.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'rexml/document'
-
-module Redmine
- module VERSION #:nodoc:
- MAJOR = 1
- MINOR = 0
- TINY = 0
-
- # Branch values:
- # * official release: nil
- # * stable branch: stable
- # * trunk: devel
- BRANCH = 'stable'
-
- # Retrieves the revision from the working copy
- def self.revision
- if File.directory?(File.join(Rails.root, '.svn'))
- begin
- path = Redmine::Scm::Adapters::AbstractAdapter.shell_quote(Rails.root.to_s)
- if `svn info --xml #{path}` =~ /revision="(\d+)"/
- return $1.to_i
- end
- rescue
- # Could not find the current revision
- end
- end
- nil
- end
-
- REVISION = self.revision
- ARRAY = [MAJOR, MINOR, TINY, BRANCH, REVISION].compact
- STRING = ARRAY.join('.')
-
- def self.to_a; ARRAY end
- def self.to_s; STRING end
- end
-end
diff --git a/trustie2/lib/redmine/views/api_template_handler.rb b/trustie2/lib/redmine/views/api_template_handler.rb
deleted file mode 100644
index 04a7d5642..000000000
--- a/trustie2/lib/redmine/views/api_template_handler.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Views
- class ApiTemplateHandler
- def self.call(template)
- "Redmine::Views::Builders.for(params[:format], request, response) do |api|; #{template.source}; self.output_buffer = api.output; end"
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/views/builders.rb b/trustie2/lib/redmine/views/builders.rb
deleted file mode 100644
index a1284fef8..000000000
--- a/trustie2/lib/redmine/views/builders.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'redmine/views/builders/json'
-require 'redmine/views/builders/xml'
-
-module Redmine
- module Views
- module Builders
- def self.for(format, request, response, &block)
- builder = case format
- when 'xml', :xml; Builders::Xml.new(request, response)
- when 'json', :json; Builders::Json.new(request, response)
- else; raise "No builder for format #{format}"
- end
- if block
- block.call(builder)
- else
- builder
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/views/builders/json.rb b/trustie2/lib/redmine/views/builders/json.rb
deleted file mode 100644
index feae6de53..000000000
--- a/trustie2/lib/redmine/views/builders/json.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'redmine/views/builders/structure'
-
-module Redmine
- module Views
- module Builders
- class Json < Structure
- attr_accessor :jsonp
-
- def initialize(request, response)
- super
- callback = request.params[:callback] || request.params[:jsonp]
- if callback && Setting.jsonp_enabled?
- self.jsonp = callback.to_s.gsub(/[^a-zA-Z0-9_]/, '')
- end
- end
-
- def output
- json = @struct.first.to_json
- if jsonp.present?
- json = "#{jsonp}(#{json})"
- response.content_type = 'application/javascript'
- end
- json
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/views/builders/structure.rb b/trustie2/lib/redmine/views/builders/structure.rb
deleted file mode 100644
index a26154976..000000000
--- a/trustie2/lib/redmine/views/builders/structure.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'blankslate'
-
-module Redmine
- module Views
- module Builders
- class Structure < BlankSlate
- attr_accessor :request, :response
-
- def initialize(request, response)
- @struct = [{}]
- self.request = request
- self.response = response
- end
-
- def array(tag, options={}, &block)
- @struct << []
- block.call(self)
- ret = @struct.pop
- @struct.last[tag] = ret
- @struct.last.merge!(options) if options
- end
-
- def method_missing(sym, *args, &block)
- if args.any?
- if args.first.is_a?(Hash)
- if @struct.last.is_a?(Array)
- @struct.last << args.first unless block
- else
- @struct.last[sym] = args.first
- end
- else
- if @struct.last.is_a?(Array)
- if args.size == 1 && !block_given?
- @struct.last << args.first
- else
- @struct.last << (args.last || {}).merge(:value => args.first)
- end
- else
- @struct.last[sym] = args.first
- end
- end
- end
-
- if block
- @struct << (args.first.is_a?(Hash) ? args.first : {})
- block.call(self)
- ret = @struct.pop
- if @struct.last.is_a?(Array)
- @struct.last << ret
- else
- if @struct.last.has_key?(sym) && @struct.last[sym].is_a?(Hash)
- @struct.last[sym].merge! ret
- else
- @struct.last[sym] = ret
- end
- end
- end
- end
-
- def output
- raise "Need to implement #{self.class.name}#output"
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/views/builders/xml.rb b/trustie2/lib/redmine/views/builders/xml.rb
deleted file mode 100644
index 8bee3fd1a..000000000
--- a/trustie2/lib/redmine/views/builders/xml.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'builder'
-
-module Redmine
- module Views
- module Builders
- class Xml < ::Builder::XmlMarkup
- def initialize(request, response)
- super()
- instruct!
- end
-
- def output
- target!
- end
-
- def method_missing(sym, *args, &block)
- if args.size == 1 && args.first.is_a?(::Time)
- __send__ sym, args.first.xmlschema, &block
- else
- super
- end
- end
-
- def array(name, options={}, &block)
- __send__ name, (options || {}).merge(:type => 'array'), &block
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/views/labelled_form_builder.rb b/trustie2/lib/redmine/views/labelled_form_builder.rb
deleted file mode 100644
index 2bba17faf..000000000
--- a/trustie2/lib/redmine/views/labelled_form_builder.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'action_view/helpers/form_helper'
-
-class Redmine::Views::LabelledFormBuilder < ActionView::Helpers::FormBuilder
- include Redmine::I18n
-
- (field_helpers.map(&:to_s) - %w(radio_button hidden_field fields_for) +
- %w(date_select)).each do |selector|
- src = <<-END_SRC
- def #{selector}(field, options = {})
- label_for_field(field, options) + super(field, options.except(:label)).html_safe
- end
- END_SRC
- class_eval src, __FILE__, __LINE__
- end
-
- def select(field, choices, options = {}, html_options = {})
- label_for_field(field, options) + super(field, choices, options, html_options.except(:label)).html_safe
- end
-
- def time_zone_select(field, priority_zones = nil, options = {}, html_options = {})
- label_for_field(field, options) + super(field, priority_zones, options, html_options.except(:label)).html_safe
- end
-
- # Returns a label tag for the given field
- def label_for_field(field, options = {})
- return ''.html_safe if options.delete(:no_label)
- text = options[:label].is_a?(Symbol) ? l(options[:label]) : options[:label]
- text ||= l(("field_" + field.to_s.gsub(/\_id$/, "")).to_sym)
- text += @template.content_tag("span", " *", :class => "required") if options.delete(:required)
- @template.content_tag("label", text.html_safe,
- :class => (@object && @object.errors[field].present? ? "error" : nil),
- :for => (@object_name.to_s + "_" + field.to_s))
- end
-end
diff --git a/trustie2/lib/redmine/views/my_page/block.rb b/trustie2/lib/redmine/views/my_page/block.rb
deleted file mode 100644
index dd664acad..000000000
--- a/trustie2/lib/redmine/views/my_page/block.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Views
- module MyPage
- module Block
- def self.additional_blocks
- @@additional_blocks ||= Dir.glob("#{Redmine::Plugin.directory}/*/app/views/my/blocks/_*.{rhtml,erb}").inject({}) do |h,file|
- name = File.basename(file).split('.').first.gsub(/^_/, '')
- h[name] = name.to_sym
- h
- end
- end
- end
- end
- end
-end
diff --git a/trustie2/lib/redmine/views/other_formats_builder.rb b/trustie2/lib/redmine/views/other_formats_builder.rb
deleted file mode 100644
index 0093ff63a..000000000
--- a/trustie2/lib/redmine/views/other_formats_builder.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 Views
- class OtherFormatsBuilder
- def initialize(view)
- @view = view
- end
-
- def link_to(name, options={})
- url = { :format => name.to_s.downcase }.merge(options.delete(:url) || {}).except('page')
- caption = options.delete(:caption) || name
- html_options = { :class => name.to_s.downcase, :rel => 'nofollow' }.merge(options)
- @view.content_tag('span', @view.link_to(caption, url, html_options))
- end
- end
- end
-end
diff --git a/trustie2/lib/seems_rateable/Gemfile b/trustie2/lib/seems_rateable/Gemfile
deleted file mode 100644
index a1025271a..000000000
--- a/trustie2/lib/seems_rateable/Gemfile
+++ /dev/null
@@ -1,23 +0,0 @@
-source "https://rubygems.org"
-
-# Declare your gem's dependencies in seems_rateable.gemspec.
-# Bundler will treat runtime dependencies like base dependencies, and
-# development dependencies will be added by default to the :development group.
-gemspec
-
-# Declare any dependencies that are still in development here instead of in
-# your gemspec. These might include edge Rails or gems from your path or
-# Git. Remember to move these dependencies to your gemspec before releasing
-# your gem to rubygems.org.
-
-# To use debugger
-# gem 'debugger'
-
-
-group :development do
- gem 'sqlite3'
- gem 'jquery-rails'
- gem 'twitter-bootstrap-rails'
- gem 'sorcery'
-end
-
diff --git a/trustie2/lib/seems_rateable/MIT-LICENSE b/trustie2/lib/seems_rateable/MIT-LICENSE
deleted file mode 100644
index df448fb9f..000000000
--- a/trustie2/lib/seems_rateable/MIT-LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright 2013 YOURNAME
-
-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, title 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.
diff --git a/trustie2/lib/seems_rateable/README.md b/trustie2/lib/seems_rateable/README.md
deleted file mode 100644
index aacc7407b..000000000
--- a/trustie2/lib/seems_rateable/README.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# SeemsRateable
-
-Star rating gem for Rails application using jQuery plugin jRating
-
-## Demo
-
-Demo application, requires to sign up before rating
-
-## Instructions
-
-### Installation
-
-Add this line to your application's Gemfile:
-
- gem 'seems_rateable'
-
-And then execute:
-
- $ bundle
-
-Or install it yourself as:
-
- $ gem install seems_rateable
-
-### Generation
-
- $ rails generate seems_rateable:install
-
-Generator creates migration files, javascript files and initializer
-
-### Prepare
-
-Require javascript files by adding this line to application.js
-
- #application.js
- //= require_directory ./rateable
-
-Add seems_rateable to routes.rb file
-
-Include stylesheet adding <%= seems_rateable_stylesheet %> to your layout header
-
-Also make sure you have an existing current_user helper method
-
-Don't forget to run
-
- $ rake db:migrate
-
-To prepare model add seems_rateable to your rateable model file. You can also pass a hash of options to
-customize the functionality
-
-
-:dimensionsArray of dimensions e.g :dimensions => [:quality, :quantity]
-:allow_updateAllowing user to re-rate his own ratings, default set to false e.g :allow_update=> true
-
-
- class Post < ActiveRecord::Base
- seems_rateable :allow_update => true, :dimensions => [:quality, :length]
- end
-
-To access object's rates use rates method, to get dimension rates pass an argument eg :
-
- @object.rates
- @object.rates(:quality)
- @object.rates(:quantity)
-
-This also applies to cached average rating e.g
-
- @object.average
- @object.average(:quality)
- @object.average(:quantity)
-
-And to object's raters e.g
-
- @object.raters
- @object.raters(:quality)
- @object.raters(:quantity)
-
-To track user's given ratings add seems_rateable_rater to your rater model.
-If your rater class is not "User"(e.g "Client" or "Customer") change configuration in initializer generated by this engine.
-Now you can access user's ratings by @user.ratings_given
-
-### Usage
-
-To display star rating use helper method rating_for in your view
-
- #index.html.erb
-
- rating_for @post
-
- rating_for @post, :dimension => :quality, :class => 'post', :id => 'list'
-
- rating_for @post, :static => true
-
-You can specify these options :
-
-:dimensionThe dimension of the object
-:staticSet to true to display static star rating, default false
-:classClass of the div, default set to 'rateable'
-:idID of the div e.g :id => "info", default nil
-
-
-To edit the javascript options locate rateable.js file in /app/assets/javascripts/rateable/.
-The javascript options are explained directly in the file
-
-## Contributing
-
-1. Fork it
-2. Create your feature branch (`git checkout -b my-new-feature`)
-3. Commit your changes (`git commit -am 'Add some feature'`)
-4. Push to the branch (`git push origin my-new-feature`)
-5. Create new Pull Request
diff --git a/trustie2/lib/seems_rateable/Rakefile b/trustie2/lib/seems_rateable/Rakefile
deleted file mode 100644
index cc267251e..000000000
--- a/trustie2/lib/seems_rateable/Rakefile
+++ /dev/null
@@ -1,17 +0,0 @@
-begin
- require 'bundler/setup'
-rescue LoadError
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
-end
-
-require 'rdoc/task'
-
-RDoc::Task.new(:rdoc) do |rdoc|
- rdoc.rdoc_dir = 'rdoc'
- rdoc.title = 'SeemsRateable'
- rdoc.options << '--line-numbers'
- rdoc.rdoc_files.include('README.md')
- rdoc.rdoc_files.include('lib/**/*.rb')
-end
-
-Bundler::GemHelper.install_tasks
diff --git a/trustie2/lib/seems_rateable/app/assets/images/seems_rateable/bg_jRatingInfos.png b/trustie2/lib/seems_rateable/app/assets/images/seems_rateable/bg_jRatingInfos.png
deleted file mode 100644
index af5bf556e..000000000
Binary files a/trustie2/lib/seems_rateable/app/assets/images/seems_rateable/bg_jRatingInfos.png and /dev/null differ
diff --git a/trustie2/lib/seems_rateable/app/assets/images/seems_rateable/small.png b/trustie2/lib/seems_rateable/app/assets/images/seems_rateable/small.png
deleted file mode 100644
index de1826f59..000000000
Binary files a/trustie2/lib/seems_rateable/app/assets/images/seems_rateable/small.png and /dev/null differ
diff --git a/trustie2/lib/seems_rateable/app/assets/images/seems_rateable/stars.png b/trustie2/lib/seems_rateable/app/assets/images/seems_rateable/stars.png
deleted file mode 100644
index 2df62b026..000000000
Binary files a/trustie2/lib/seems_rateable/app/assets/images/seems_rateable/stars.png and /dev/null differ
diff --git a/trustie2/lib/seems_rateable/app/assets/javascripts/seems_rateable/application.js b/trustie2/lib/seems_rateable/app/assets/javascripts/seems_rateable/application.js
deleted file mode 100644
index 806c8cc06..000000000
--- a/trustie2/lib/seems_rateable/app/assets/javascripts/seems_rateable/application.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// This is a manifest file that'll be compiled into application.js, which will include all the files
-// listed below.
-//
-// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
-// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
-//
-// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
-// compiled file.
-//
-// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
-// about supported directives.
-
-//= require_tree .
-
-
diff --git a/trustie2/lib/seems_rateable/app/assets/stylesheets/seems_rateable/application.css b/trustie2/lib/seems_rateable/app/assets/stylesheets/seems_rateable/application.css
deleted file mode 100644
index aeb6475f3..000000000
--- a/trustie2/lib/seems_rateable/app/assets/stylesheets/seems_rateable/application.css
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * This is a manifest file that'll be compiled into application.css, which will include all the files
- * listed below.
- *
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
- * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
- *
- * You're free to add application-wide styles to this file and they'll appear at the top of the
- * compiled file, but it's generally better to create a new file per style scope.
- *
- *= require_self
- *= require_tree .
- */
-
-/*********************/
-/** jRating CSS **/
-/*********************/
-
-/**Div containing the color of the stars */
-
-
-.jRatingAverage {
- background-color:#f62929;
- position:relative;
- top:0;
- left:0;
- z-index:2;
- height:100%;
-}
-.jRatingColor {
- background-color:#FFD400; /* bgcolor of the stars*/
- position:relative;
- top:0;
- left:0;
- z-index:2;
- height:100%;
-}
-
-/** Div containing the stars **/
-.jStar {
- position:relative;
- left:0;
- z-index:3;
-}
-
-/** P containing the rate informations **/
-p.jRatingInfos {
- position: absolute;
- z-index:9999;
- background: transparent url('bg_jRatingInfos.png') no-repeat;
- color: #CACACA;
- display: none;
- width: 91px;
- height: 29px;
- font-size:16px;
- text-align:center;
- padding-top:5px;
-}
-p.jRatingInfos span.maxRate {
- color:#c9c9c9;
- font-size:14px;
-}
diff --git a/trustie2/lib/seems_rateable/app/controllers/seems_rateable/application_controller.rb b/trustie2/lib/seems_rateable/app/controllers/seems_rateable/application_controller.rb
deleted file mode 100644
index 7f0af9fc5..000000000
--- a/trustie2/lib/seems_rateable/app/controllers/seems_rateable/application_controller.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module SeemsRateable
- class ApplicationController < ::ApplicationController
- rescue_from SeemsRateable::Errors::AlreadyRatedError do |exception|
- render :json => {:error => true}
- end
- end
-end
diff --git a/trustie2/lib/seems_rateable/app/controllers/seems_rateable/ratings_controller.rb b/trustie2/lib/seems_rateable/app/controllers/seems_rateable/ratings_controller.rb
deleted file mode 100644
index 4c8758f08..000000000
--- a/trustie2/lib/seems_rateable/app/controllers/seems_rateable/ratings_controller.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require_dependency "seems_rateable/application_controller"
-
-module SeemsRateable
- class RatingsController < ApplicationController
- def create
- raise Errors::NoCurrentUserInstanceError unless current_user
- obj = params[:kls].classify.constantize.find(params[:idBox])
- obj.rate(params[:rate].to_i, current_user.id, params[:dimension])
-
- render :json => true
-
- rescue Errors::NoCurrentUserInstanceError
- render :json => {:error => 'you must be login.'}
- end
- end
-end
diff --git a/trustie2/lib/seems_rateable/app/models/seems_rateable/cached_rating.rb b/trustie2/lib/seems_rateable/app/models/seems_rateable/cached_rating.rb
deleted file mode 100644
index c48ff0734..000000000
--- a/trustie2/lib/seems_rateable/app/models/seems_rateable/cached_rating.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module SeemsRateable
- class CachedRating < ActiveRecord::Base
- belongs_to :cacheable, :polymorphic => true
- end
-end
diff --git a/trustie2/lib/seems_rateable/app/models/seems_rateable/rate.rb b/trustie2/lib/seems_rateable/app/models/seems_rateable/rate.rb
deleted file mode 100644
index 8259ca1e7..000000000
--- a/trustie2/lib/seems_rateable/app/models/seems_rateable/rate.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module SeemsRateable
- class Rate < ActiveRecord::Base
- belongs_to :rater, :class_name => SeemsRateable::Engine.config.owner_class
- belongs_to :rateable, :polymorphic => true
- end
-end
diff --git a/trustie2/lib/seems_rateable/bin/rails b/trustie2/lib/seems_rateable/bin/rails
deleted file mode 100644
index 773450b9c..000000000
--- a/trustie2/lib/seems_rateable/bin/rails
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env ruby1.9.1
-# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
-
-ENGINE_ROOT = File.expand_path('../..', __FILE__)
-ENGINE_PATH = File.expand_path('../../lib/seems_rateable/engine', __FILE__)
-
-require 'rails/all'
-require 'rails/engine/commands'
diff --git a/trustie2/lib/seems_rateable/config/routes.rb b/trustie2/lib/seems_rateable/config/routes.rb
deleted file mode 100644
index 4191f5460..000000000
--- a/trustie2/lib/seems_rateable/config/routes.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-SeemsRateable::Engine.routes.draw do
- resources :ratings, :only => :create
-end
diff --git a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/install_generator.rb b/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/install_generator.rb
deleted file mode 100644
index 613bdac72..000000000
--- a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/install_generator.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require 'rails/generators/migration'
-require 'fileutils'
-
-module SeemsRateable
- module Generators
- class InstallGenerator < ::Rails::Generators::Base
- include Rails::Generators::Migration
- source_root File.expand_path('../templates', __FILE__)
-
- def self.next_migration_number(path)
- unless @prev_migration_nr
- @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
- else
- @prev_migration_nr += 1
- end
- @prev_migration_nr.to_s
- end
-
- def routegen
- route("seems_rateable")
- end
-
- desc "generating migration files"
- def copy_migrations
- migration_template "rates_migration.rb", "db/migrate/create_seems_rateable_rates.rb"
- migration_template "cached_ratings_migration.rb", "db/migrate/create_seems_rateable_cached_ratings.rb"
- end
-
- desc "generating initializer"
- def copy_initializer
- template "initializer.rb", "config/initializers/seems_rateable.rb"
- end
-
- desc "generating javascript files"
- def copy_javascript_asset
- Dir.mkdir "app/assets/javascripts/rateable" unless File.directory?("app/assets/javascripts/rateable")
- copy_file "rateable.js.erb", "app/assets/javascripts/rateable/rateable.js.erb" unless File.exists?("app/assets/javascripts/rateable/rateable.js.erb")
- copy_file "jRating.js.erb", "app/assets/javascripts/rateable/jRating.js.erb" unless File.exists?("app/assets/javascripts/rateable/jRating.js.erb")
- end
- end
- end
-end
diff --git a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/cached_ratings_migration.rb b/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/cached_ratings_migration.rb
deleted file mode 100644
index e3e7ab2ee..000000000
--- a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/cached_ratings_migration.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-class CreateSeemsRateableCachedRatings < ActiveRecord::Migration
- def self.up
- create_table :seems_rateable_cached_ratings do |t|
- t.belongs_to :cacheable, :polymorphic => true
- t.float :avg, :null => false
- t.integer :cnt, :null => false
- t.string :dimension
- t.integer :cacheable_id, :limit => 8
- t.string :cacheable_type
- t.timestamps
- end
- end
-
- def self.down
- drop_table :cached_ratings
- end
-end
diff --git a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/initializer.rb b/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/initializer.rb
deleted file mode 100644
index 2391948fa..000000000
--- a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/initializer.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-#SeemsRateable engine Initializer
-
-#Configure owner class of the given ratings
-SeemsRateable::Engine.config.owner_class = "User"
diff --git a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/jRating.js.erb b/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/jRating.js.erb
deleted file mode 100644
index b5b778889..000000000
--- a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/jRating.js.erb
+++ /dev/null
@@ -1,225 +0,0 @@
-/************************************************************************
-*************************************************************************
-@Name : jRating - jQuery Plugin
-@Revison : 3.0
-@Date : 28/01/2013
-@Author: ALPIXEL - (www.myjqueryplugins.com - www.alpixel.fr)
-@License : Open Source - MIT License : http://www.opensource.org/licenses/mit-license.php
-
-**************************************************************************
-*************************************************************************/
-(function($) {
- $.fn.jRating = function(op) {
- var defaults = {
- /** String vars **/
- bigStarsPath : 'images/seems_rateable/stars.png', // path of the icon stars.png
- smallStarsPath : 'images/seems_rateable/small.png', // path of the icon small.png
- path : '/ratings',
- type : 'big', // can be set to 'small' or 'big'
-
- /** Boolean vars **/
- step:false, // if true, mouseover binded star by star,
- isDisabled:false,
- showRateInfo: false,
- canRateAgain : false,
-
- /** Integer vars **/
- length:5, // number of star to display
- decimalLength : 0, // number of decimals.. Max 3, but you can complete the function 'getNote'
- rateMax : 20, // maximal rate - integer from 0 to 9999 (or more)
- rateInfosX : -45, // relative position in X axis of the info box when mouseover
- rateInfosY : 5, // relative position in Y axis of the info box when mouseover
- nbRates : 1,
-
- /** Functions **/
- onSuccess : null,
- onError : null
- };
-
- if(this.length>0)
- return this.each(function() {
- /*vars*/
- var opts = $.extend(defaults, op),
- newWidth = 0,
- starWidth = 0,
- starHeight = 0,
- bgPath = '',
- hasRated = false,
- globalWidth = 0,
- nbOfRates = opts.nbRates;
-
- if($(this).hasClass('jDisabled') || opts.isDisabled)
- var jDisabled = true;
- else
- var jDisabled = false;
-
- getStarWidth();
- $(this).height(starHeight);
-
-
-
- var average = parseFloat($(this).attr('data-average')), // get the average of all rates
- idBox = parseInt($(this).attr('data-id')), // get the id of the box
- kls = $(this).attr('data-kls'),
- dimension = $(this).attr('data-dimension'),
- widthRatingContainer = starWidth*opts.length, // Width of the Container
- widthColor = average/opts.rateMax*widthRatingContainer, // Width of the color Container
- quotient =
- $('',
- {
- 'class' : 'jRatingColor',
- css:{
- width:widthColor
- }
- }).appendTo($(this)),
-
- average =
- $('',
- {
- 'class' : 'jRatingAverage',
- css:{
- width:0,
- top:- starHeight
- }
- }).appendTo($(this)),
-
- jstar =
- $('',
- {
- 'class' : 'jStar',
- css:{
- width:widthRatingContainer,
- height:starHeight,
- top:- (starHeight*2),
- background: 'url('+bgPath+') repeat-x'
- }
- }).appendTo($(this));
-
- $(this).css({width: widthRatingContainer,overflow:'hidden',zIndex:1,position:'relative'});
-
- if(!jDisabled)
- $(this).unbind().bind({
- mouseenter : function(e){
- var realOffsetLeft = findRealLeft(this);
- var relativeX = e.pageX - realOffsetLeft;
- if (opts.showRateInfo)
- var tooltip =
- $('',{
- 'class' : 'jRatingInfos',
- html : getNote(relativeX)+' / '+opts.rateMax+'',
- css : {
- top: (e.pageY + opts.rateInfosY),
- left: (e.pageX + opts.rateInfosX)
- }
- }).appendTo('body').show();
- },
- mouseover : function(e){
- $(this).css('cursor','pointer');
- },
- mouseout : function(){
- $(this).css('cursor','default');
- if(hasRated) average.width(globalWidth);
- else average.width(0);
- },
- mousemove : function(e){
- var realOffsetLeft = findRealLeft(this);
- var relativeX = e.pageX - realOffsetLeft;
- if(opts.step) newWidth = Math.floor(relativeX/starWidth)*starWidth + starWidth;
- else newWidth = relativeX;
- average.width(newWidth);
- if (opts.showRateInfo)
- $("p.jRatingInfos")
- .css({
- left: (e.pageX + opts.rateInfosX)
- })
- .html(getNote(newWidth) +' / '+opts.rateMax+'');
- },
- mouseleave : function(){
- $("p.jRatingInfos").remove();
- },
- click : function(e){
- var element = this;
-
- /*set vars*/
- hasRated = true;
- globalWidth = newWidth;
- nbOfRates--;
-
- if(!opts.canRateAgain || parseInt(nbOfRates) <= 0) $(this).unbind().css('cursor','default').addClass('jDisabled');
-
- if (opts.showRateInfo) $("p.jRatingInfos").fadeOut('fast',function(){$(this).remove();});
- e.preventDefault();
- var rate = getNote(newWidth);
- average.width(newWidth);
-
-
- $.post(defaults.path,
- {
- idBox : idBox,
- rate : rate,
- kls : kls,
- dimension : dimension
- /** action : 'rating' **/
- },
- function(data) {
- if(!data.error)
- {
- /** Here you can display an alert box,
- or use the jNotify Plugin :) http://www.myqjqueryplugins.com/jNotify
- exemple : */
- if(opts.onSuccess) opts.onSuccess( element, rate );
- }
- else
- {
-
- /** Here you can display an alert box,
- or use the jNotify Plugin :) http://www.myqjqueryplugins.com/jNotify
- exemple : */
- if(opts.onError) opts.onError( element, rate );
- }
- },
- 'json'
- );
- }
- });
-
- function getNote(relativeX) {
- var noteBrut = parseFloat((relativeX*100/widthRatingContainer)*opts.rateMax/100);
- switch(opts.decimalLength) {
- case 1 :
- var note = Math.round(noteBrut*10)/10;
- break;
- case 2 :
- var note = Math.round(noteBrut*100)/100;
- break;
- case 3 :
- var note = Math.round(noteBrut*1000)/1000;
- break;
- default :
- var note = Math.round(noteBrut*1)/1;
- }
- return note;
- };
-
- function getStarWidth(){
- switch(opts.type) {
- case 'small' :
- starWidth = 12; // width of the picture small.png
- starHeight = 10; // height of the picture small.png
- bgPath = opts.smallStarsPath;
- break;
- default :
- starWidth = 23; // width of the picture stars.png
- starHeight = 20; // height of the picture stars.png
- bgPath = opts.bigStarsPath;
- }
- };
-
- function findRealLeft(obj) {
- if( !obj ) return 0;
- return obj.offsetLeft + findRealLeft( obj.offsetParent );
- };
- });
-
- }
-})(jQuery);
diff --git a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/rateable.js.erb b/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/rateable.js.erb
deleted file mode 100644
index e926601d2..000000000
--- a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/rateable.js.erb
+++ /dev/null
@@ -1,25 +0,0 @@
-$(document).ready(function(){
- $(".rateable").jRating({
- //default options displayed below ->
-
- rateMax: 5, //Maximal rate
- length : 5, //Number of stars
- //decimalLength : 0, //Number of decimals in the rate
- //type : 'big', //Big or small
- //step : true, //If set to true, filling of the stars is done star by star (step by step).
- //isDisabled: false, //Set true to display static rating
- //showRateInfo:false, //Rate info panel, set true to display
- //rateInfosX : 45, //In pixel - Absolute left position of the information box during mousemove.
- //rateInfosY : 5, //In pixel - Absolute top position of the information box during mousemove.
- path : '/ratings',
- onSuccess : function(element, rate){
- //something like ->
- //alert('success');
- $('Thanks for rating!').insertAfter(element)
- },
- onError : function(element, rate) {
- $('You have already rated!').insertAfter(element)
- }
- });
-
-});
diff --git a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/rates_migration.rb b/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/rates_migration.rb
deleted file mode 100644
index 21990b0ad..000000000
--- a/trustie2/lib/seems_rateable/lib/generators/seems_rateable/install/templates/rates_migration.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-class CreateSeemsRateableRates < ActiveRecord::Migration
- def self.up
- create_table :seems_rateable_rates do |t|
- t.belongs_to :rater
- t.belongs_to :rateable, :polymorphic => true
- t.float :stars, :null => false
- t.integer :rater_id, :limit => 8
- t.integer :rateable_id
- t.string :rateable_type
- t.string :dimension
- t.timestamps
- end
- end
-
- def self.down
- drop_table :rates
- end
-end
diff --git a/trustie2/lib/seems_rateable/lib/seems_rateable.rb b/trustie2/lib/seems_rateable/lib/seems_rateable.rb
deleted file mode 100644
index 2939d773f..000000000
--- a/trustie2/lib/seems_rateable/lib/seems_rateable.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-begin
- require 'rails'
-rescue LoadError
-end
-
-require "jquery-rails"
-
-require "seems_rateable/engine"
-require "seems_rateable/errors"
-require "seems_rateable/helpers"
-require "seems_rateable/model"
-require "seems_rateable/routes"
-require "seems_rateable/version"
-
-module SeemsRateable
-end
diff --git a/trustie2/lib/seems_rateable/lib/seems_rateable/engine.rb b/trustie2/lib/seems_rateable/lib/seems_rateable/engine.rb
deleted file mode 100644
index f32ccb929..000000000
--- a/trustie2/lib/seems_rateable/lib/seems_rateable/engine.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-module SeemsRateable
- class Engine < ::Rails::Engine
- isolate_namespace SeemsRateable
-
- config.generators do |g|
- g.test_framework :rspec, :fixture => false
- g.fixture_replacement :factory_girl, :dir => 'spec/factories'
- end
-
- initializer :seems_rateable do
- ActiveRecord::Base.send :include, SeemsRateable::Model
- ActionView::Base.send :include, SeemsRateable::Helpers
- ActionDispatch::Routing::Mapper.send :include, SeemsRateable::Routes
- end
- end
-end
diff --git a/trustie2/lib/seems_rateable/lib/seems_rateable/errors.rb b/trustie2/lib/seems_rateable/lib/seems_rateable/errors.rb
deleted file mode 100644
index 9fcb0c380..000000000
--- a/trustie2/lib/seems_rateable/lib/seems_rateable/errors.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-module SeemsRateable
- module Errors
- class InvalidRateableObjectError < StandardError
- def to_s
- "Stated object is not rateable. Add 'seems_rateable' to your object's class model."
- end
- end
-
- class NoCurrentUserInstanceError < StandardError
- def to_s
- "User instance current_user is not available."
- end
- end
-
- class AlreadyRatedError < StandardError
- def to_s
- "User has already rated an object."
- end
- end
- end
-end
diff --git a/trustie2/lib/seems_rateable/lib/seems_rateable/helpers.rb b/trustie2/lib/seems_rateable/lib/seems_rateable/helpers.rb
deleted file mode 100644
index 3d79adf79..000000000
--- a/trustie2/lib/seems_rateable/lib/seems_rateable/helpers.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-module SeemsRateable
- module Helpers
- def rating_for(obj, opts={})
- raise Errors::InvalidRateableObjectError unless obj.class.respond_to?(:rateable?)
-
- options = {
- :dimension => nil,
- :static => false,
- :class => 'rateable',
- :id => nil
- }.update(opts)
-
- content_tag :div, "", "data-average" => obj.average(options[:dimension]) ? obj.average(options[:dimension]).avg : 0, :id => options[:id],
- :class => "#{options[:class]}#{jdisabled?(options[:static])}",
- "data-id" => obj.id, "data-kls" => obj.class.name, "data-dimension" => options[:dimension]
- end
-
- def seems_rateable_stylesheet
- stylesheet_link_tag "seems_rateable/application", media: "all", "data-turbolinks-track" => true
- end
-
- private
- def jdisabled?(option)
- " jDisabled" if option || !current_user
- end
- end
-end
diff --git a/trustie2/lib/seems_rateable/lib/seems_rateable/model.rb b/trustie2/lib/seems_rateable/lib/seems_rateable/model.rb
deleted file mode 100644
index b4ebbb196..000000000
--- a/trustie2/lib/seems_rateable/lib/seems_rateable/model.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-require 'active_support/concern'
-
-module SeemsRateable
- module Model
- extend ActiveSupport::Concern
-
- def rate(stars, user_id, dimension=nil)
- if !has_rated?(user_id, dimension)
- self.rates.create do |r|
- r.stars = stars
- r.rater_id = user_id
- r.dimension = dimension
- end
- update_overall_average_rating(stars, dimension)
- elsif has_rated?(user_id, dimension) && can_update?
- update_users_rating(stars, user_id, dimension)
- else
- raise Errors::AlreadyRatedError
- end
- end
-
- def update_overall_average_rating(stars, dimension=nil)
- r = average(dimension)
- if r.nil?
- self.rate_averages.create do |r|
- r.avg = stars
- r.dimension = dimension
- r.cnt = 1
- end
- else
- r.avg = (r.avg * r.cnt + stars) / (r.cnt+1)
- r.cnt += 1
- r.save!
- r
- end
- end
-
- def update_users_rating(stars, user_id, dimension=nil)
- obj = rates(dimension).where(:rater_id => user_id).first
- current_record = average(dimension)
- current_record.avg = (current_record.avg*current_record.cnt - obj.stars + stars) / (current_record.cnt)
- current_record.save!
- obj.stars = stars
- obj.save!
- end
-
-
- def average(dimension=nil)
- rate_averages.where(dimension: dimension).first
- end
-
- def rates(dimension=nil)
- rates_all.where(dimension: dimension)
- end
-
- def raters(dimension=nil)
- raters_all.where('seems_rateable_rates.dimension = ?', dimension)
- end
-
- def has_rated?(user_id, dimension=nil)
- record = self.rates(dimension).where(:rater_id => user_id)
- record.empty? ? false : true
- end
-
- def can_update?
- self.class.can_update?
- end
-
- module ClassMethods
- def seems_rateable(opts={})
- has_many :rates_all, :as => :rateable, :class_name => SeemsRateable::Rate, :dependent => :destroy
- has_many :raters_all, :through => :rates_all, :class_name => SeemsRateable::Engine.config.owner_class, :source => :rater
- has_many :rate_averages, :as => :cacheable, :class_name => SeemsRateable::CachedRating, :dependent => :destroy
-
- self.class_variable_set(:@@permission, opts[:allow_update] ? true : false)
-
- def self.can_update?
- self.class_variable_get(:@@permission)
- end
-
- def self.rateable?
- true
- end
- end
-
- def seems_rateable_rater
- has_many :ratings_given, :class_name => SeemsRateable::Rate, :foreign_key => :rater_id
- end
- end
- end
-end
diff --git a/trustie2/lib/seems_rateable/lib/seems_rateable/routes.rb b/trustie2/lib/seems_rateable/lib/seems_rateable/routes.rb
deleted file mode 100644
index 81a243339..000000000
--- a/trustie2/lib/seems_rateable/lib/seems_rateable/routes.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module SeemsRateable
- module Routes
- def seems_rateable
- mount SeemsRateable::Engine => '/rateable', :as => :rateable
- end
- end
-end
diff --git a/trustie2/lib/seems_rateable/lib/seems_rateable/version.rb b/trustie2/lib/seems_rateable/lib/seems_rateable/version.rb
deleted file mode 100644
index 8a635c656..000000000
--- a/trustie2/lib/seems_rateable/lib/seems_rateable/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module SeemsRateable
- VERSION = "1.0.13"
-end
diff --git a/trustie2/lib/seems_rateable/seems_rateable.gemspec b/trustie2/lib/seems_rateable/seems_rateable.gemspec
deleted file mode 100644
index b4f32a9fc..000000000
--- a/trustie2/lib/seems_rateable/seems_rateable.gemspec
+++ /dev/null
@@ -1,25 +0,0 @@
-$:.push File.expand_path("../lib", __FILE__)
-
-# Maintain your gem's version:
-require "seems_rateable/version"
-
-# Describe your gem and declare its dependencies:
-Gem::Specification.new do |s|
- s.name = "seems_rateable"
- s.version = SeemsRateable::VERSION
- s.authors = ["Peter Toth"]
- s.email = ["proximin@gmail.com"]
- s.homepage = "http://rateable.herokuapp.com"
- s.summary = "Star Rating Engine"
- s.description = "Star rating engine using jQuery plugin jRating for Rails applications"
-
- s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"]
-
- s.add_dependency "rails"
- s.add_dependency "jquery-rails"
-
- s.add_development_dependency "sqlite3"
- s.add_development_dependency 'rspec-rails'
- s.add_development_dependency 'capybara'
- s.add_development_dependency 'factory_girl_rails'
-end
diff --git a/trustie2/lib/tasks/ci.rake b/trustie2/lib/tasks/ci.rake
deleted file mode 100644
index 11ff67eef..000000000
--- a/trustie2/lib/tasks/ci.rake
+++ /dev/null
@@ -1,63 +0,0 @@
-desc "Run the Continous Integration tests for Redmine"
-task :ci do
- # RAILS_ENV and ENV[] can diverge so force them both to test
- ENV['RAILS_ENV'] = 'test'
- RAILS_ENV = 'test'
- Rake::Task["ci:setup"].invoke
- Rake::Task["ci:build"].invoke
- Rake::Task["ci:teardown"].invoke
-end
-
-namespace :ci do
- desc "Setup Redmine for a new build"
- task :setup do
- Rake::Task["tmp:clear"].invoke
- Rake::Task["log:clear"].invoke
- Rake::Task["db:create:all"].invoke
- Rake::Task["db:migrate"].invoke
- Rake::Task["db:schema:dump"].invoke
- Rake::Task["test:scm:setup:all"].invoke
- Rake::Task["test:scm:update"].invoke
- end
-
- desc "Build Redmine"
- task :build do
- Rake::Task["test"].invoke
- #Rake::Task["test:ui"].invoke unless RUBY_VERSION < '1.9'
- end
-
- desc "Finish the build"
- task :teardown do
- end
-end
-
-desc "Creates database.yml for the CI server"
-file 'config/database.yml' do
- require 'yaml'
- database = ENV['DATABASE_ADAPTER']
- ruby = ENV['RUBY_VER'].gsub('.', '').gsub('-', '')
- branch = ENV['BRANCH'].gsub('.', '').gsub('-', '')
- dev_db_name = "ci_#{branch}_#{ruby}_dev"
- test_db_name = "ci_#{branch}_#{ruby}_test"
-
- case database
- when 'mysql'
- dev_conf = {'adapter' => (RUBY_VERSION >= '1.9' ? 'mysql2' : 'mysql'), 'database' => dev_db_name, 'host' => 'localhost', 'username' => 'jenkins', 'password' => 'jenkins', 'encoding' => 'utf8'}
- test_conf = dev_conf.merge('database' => test_db_name)
- when 'postgresql'
- dev_conf = {'adapter' => 'postgresql', 'database' => dev_db_name, 'host' => 'localhost', 'username' => 'jenkins', 'password' => 'jenkins'}
- test_conf = dev_conf.merge('database' => test_db_name)
- when 'sqlite3'
- dev_conf = {'adapter' => 'sqlite3', 'database' => "db/#{dev_db_name}.sqlite3"}
- test_conf = dev_conf.merge('database' => "db/#{test_db_name}.sqlite3")
- when 'sqlserver'
- dev_conf = {'adapter' => 'sqlserver', 'database' => dev_db_name, 'host' => 'mssqlserver', 'port' => 1433, 'username' => 'jenkins', 'password' => 'jenkins'}
- test_conf = dev_conf.merge('database' => test_db_name)
- else
- abort "Unknown database"
- end
-
- File.open('config/database.yml', 'w') do |f|
- f.write YAML.dump({'development' => dev_conf, 'test' => test_conf})
- end
-end
diff --git a/trustie2/lib/tasks/ciphering.rake b/trustie2/lib/tasks/ciphering.rake
deleted file mode 100644
index 520aae6f5..000000000
--- a/trustie2/lib/tasks/ciphering.rake
+++ /dev/null
@@ -1,35 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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.
-
-
-namespace :db do
- desc 'Encrypts SCM and LDAP passwords in the database.'
- task :encrypt => :environment do
- unless (Repository.encrypt_all(:password) &&
- AuthSource.encrypt_all(:account_password))
- raise "Some objects could not be saved after encryption, update was rollback'ed."
- end
- end
-
- desc 'Decrypts SCM and LDAP passwords in the database.'
- task :decrypt => :environment do
- unless (Repository.decrypt_all(:password) &&
- AuthSource.decrypt_all(:account_password))
- raise "Some objects could not be saved after decryption, update was rollback'ed."
- end
- end
-end
diff --git a/trustie2/lib/tasks/clear_osp_composite_score.rake b/trustie2/lib/tasks/clear_osp_composite_score.rake
deleted file mode 100644
index 992b9433f..000000000
--- a/trustie2/lib/tasks/clear_osp_composite_score.rake
+++ /dev/null
@@ -1,126 +0,0 @@
-namespace :clear_osp_composite_score_and_view_num do
- desc 'clear osp composite_score_and_view_num'
- task :start => :environment do
-
- #if File.exist?(pid_path)
- # existing_pid = IO.read(pid_path).to_i
- # begin
- # Process.kill(0, existing_pid)
- # raise(AlreadyRunningError, "Server is already running with PID #{existing_pid}")
- # rescue Errno::ESRCH
- # STDERR.puts("Removing stale PID file at #{pid_path}")
- # FileUtils.rm(pid_path)
- # end
- #end
-
-
- # run
- # sync_composite_score
- clear_view_num_and_composite_score
- #Process.fork do
- # pid = fork do
- # Process.setsid
- # STDIN.reopen('/dev/null')
- # STDOUT.reopen('/dev/null')
- # STDERR.reopen(STDOUT)
- # run
- # end
- # FileUtils.mkdir_p(pid_dir)
- # File.open(pid_path, 'w') do |file|
- # file << pid
- # end
- #end
-
- end
-
- def clear_view_num_and_composite_score
- batch_size = 1000
-
- cur_id = 0
-
- begin
- max_id = OpenSourceProject.maximum(:id)
- puts("max: "+max_id.to_s)
- #Thread.new do
- while cur_id < max_id do
- begin
- OpenSourceProject.where("id > #{cur_id} AND id < #{cur_id+batch_size}").each do |osp|
-
- osp.update_attribute(:view_num, 0)
- osp.update_attribute(:composite_score, 0)
-
- # composite_score
-
- cur_id=osp.id
- puts("OpenSourceProject: "+cur_id.to_s)
- #puts('inside')
- end
- # rm2osp_cursor.update_attribute('cursor', cur_id)
-
- rescue Exception => e
- puts e
- end
- end
-
- rescue Exception => e
- puts e
- end
- end
-
- def sync_composite_score
- rm_osp_count = Hash.new
- osp_id_set = Set.new
-
- range = 1..70
- base_table='relative_memo_to_open_source_projects_'
- range.each do |i|
-
- ####计算一段时间内的帖子新匹配多少项目以及查询项目集合
- table = base_table+i.to_s
- rm_records = RelativeMemoToOpenSourceProject.set_table_name(table).group(:relative_memo_id).select([:relative_memo_id, 'COUNT(*) AS num'])
- osp_records = RelativeMemoToOpenSourceProject.set_table_name(table).group(:osp_id).select(:osp_id)
- rm_records.each do |record|
- ######## rm_osp_count_local中没有则添加,有则更新
- rm_osp_count[record.relative_memo_id] = ((rm_osp_count.key? record.relative_memo_id) ? (rm_osp_count[record.relative_memo_id]+record.num) : record.num)
- end
-
- osp_records.each do |record|
- osp_id_set.add record.osp_id
- end
-
- puts i
- end
-
- osp_id_set.each do |osp_id|
- osp = OpenSourceProject.find(osp_id)
- composite_score =calc_composite_score(rm_osp_count, osp_id_set, osp)
- puts composite_score
- osp.update_attribute(:composite_score, composite_score)
- end
- end
-
- def calc_composite_score hash, set, osp
- score = 0
- rm_ids=RelativeMemoToOpenSourceProject.set_table_name(RelativeMemoToOpenSourceProject.getTableName(osp.id)).where(osp_id: osp.id).select(:relative_memo_id)
- rm_ids.each do |id|
- #puts id.relative_memo_id
- #puts 1/hash[id.relative_memo_id].to_f
- #puts hash.key? id.relative_memo_id
- score+=((hash.key? id.relative_memo_id) ? 1/hash[id.relative_memo_id].to_f : 0)
- #puts score
- end
- score
- end
-
- def pid_path
- File.join(pid_dir, pid_file)
- end
-
- def pid_file
- @pid_file || 'sync_osp_status.pid'
- end
-
- def pid_dir
- File.expand_path(@pid_dir || FileUtils.pwd)
- end
-end
diff --git a/trustie2/lib/tasks/deprecated.rake b/trustie2/lib/tasks/deprecated.rake
deleted file mode 100644
index 2e6cb3b77..000000000
--- a/trustie2/lib/tasks/deprecated.rake
+++ /dev/null
@@ -1,12 +0,0 @@
-def deprecated_task(name, new_name)
- task name=>new_name do
- $stderr.puts "\nNote: The rake task #{name} has been deprecated, please use the replacement version #{new_name}"
- end
-end
-
-deprecated_task :load_default_data, "redmine:load_default_data"
-deprecated_task :migrate_from_mantis, "redmine:migrate_from_mantis"
-deprecated_task :migrate_from_trac, "redmine:migrate_from_trac"
-deprecated_task "db:migrate_plugins", "redmine:plugins:migrate"
-deprecated_task "db:migrate:plugin", "redmine:plugins:migrate"
-deprecated_task :generate_session_store, :generate_secret_token
diff --git a/trustie2/lib/tasks/email.rake b/trustie2/lib/tasks/email.rake
deleted file mode 100644
index 934070e54..000000000
--- a/trustie2/lib/tasks/email.rake
+++ /dev/null
@@ -1,198 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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.
-
-namespace :redmine do
- namespace :email do
-
- desc <<-END_DESC
-Read an email from standard input.
-
-General options:
- unknown_user=ACTION how to handle emails from an unknown user
- ACTION can be one of the following values:
- ignore: email is ignored (default)
- accept: accept as anonymous user
- create: create a user account
- no_permission_check=1 disable permission checking when receiving
- the email
- no_account_notice=1 disable new user account notification
- default_group=foo,bar adds created user to foo and bar groups
-
-Issue attributes control options:
- project=PROJECT identifier of the target project
- status=STATUS name of the target status
- tracker=TRACKER name of the target tracker
- category=CATEGORY name of the target category
- priority=PRIORITY name of the target priority
- allow_override=ATTRS allow email content to override attributes
- specified by previous options
- ATTRS is a comma separated list of attributes
-
-Examples:
- # No project specified. Emails MUST contain the 'Project' keyword:
- rake redmine:email:read RAILS_ENV="production" < raw_email
-
- # Fixed project and default tracker specified, but emails can override
- # both tracker and priority attributes:
- rake redmine:email:read RAILS_ENV="production" \\
- project=foo \\
- tracker=bug \\
- allow_override=tracker,priority < raw_email
-END_DESC
-
- task :read => :environment do
- options = { :issue => {} }
- %w(project status tracker category priority).each { |a| options[:issue][a.to_sym] = ENV[a] if ENV[a] }
- options[:allow_override] = ENV['allow_override'] if ENV['allow_override']
- options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user']
- options[:no_permission_check] = ENV['no_permission_check'] if ENV['no_permission_check']
- options[:no_account_notice] = ENV['no_account_notice'] if ENV['no_account_notice']
- options[:default_group] = ENV['default_group'] if ENV['default_group']
-
- MailHandler.receive(STDIN.read, options)
- end
-
- desc <<-END_DESC
-Read emails from an IMAP server.
-
-General options:
- unknown_user=ACTION how to handle emails from an unknown user
- ACTION can be one of the following values:
- ignore: email is ignored (default)
- accept: accept as anonymous user
- create: create a user account
- no_permission_check=1 disable permission checking when receiving
- the email
- no_account_notice=1 disable new user account notification
- default_group=foo,bar adds created user to foo and bar groups
-
-Available IMAP options:
- host=HOST IMAP server host (default: 127.0.0.1)
- port=PORT IMAP server port (default: 143)
- ssl=SSL Use SSL? (default: false)
- username=USERNAME IMAP account
- password=PASSWORD IMAP password
- folder=FOLDER IMAP folder to read (default: INBOX)
-
-Issue attributes control options:
- project=PROJECT identifier of the target project
- status=STATUS name of the target status
- tracker=TRACKER name of the target tracker
- category=CATEGORY name of the target category
- priority=PRIORITY name of the target priority
- allow_override=ATTRS allow email content to override attributes
- specified by previous options
- ATTRS is a comma separated list of attributes
-
-Processed emails control options:
- move_on_success=MAILBOX move emails that were successfully received
- to MAILBOX instead of deleting them
- move_on_failure=MAILBOX move emails that were ignored to MAILBOX
-
-Examples:
- # No project specified. Emails MUST contain the 'Project' keyword:
-
- rake redmine:email:receive_imap RAILS_ENV="production" \\
- host=imap.foo.bar username=redmine@example.net password=xxx
-
-
- # Fixed project and default tracker specified, but emails can override
- # both tracker and priority attributes:
-
- rake redmine:email:receive_imap RAILS_ENV="production" \\
- host=imap.foo.bar username=redmine@example.net password=xxx ssl=1 \\
- project=foo \\
- tracker=bug \\
- allow_override=tracker,priority
-END_DESC
-
- task :receive_imap => :environment do
- imap_options = {:host => ENV['host'],
- :port => ENV['port'],
- :ssl => ENV['ssl'],
- :username => ENV['username'],
- :password => ENV['password'],
- :folder => ENV['folder'],
- :move_on_success => ENV['move_on_success'],
- :move_on_failure => ENV['move_on_failure']}
-
- options = { :issue => {} }
- %w(project status tracker category priority).each { |a| options[:issue][a.to_sym] = ENV[a] if ENV[a] }
- options[:allow_override] = ENV['allow_override'] if ENV['allow_override']
- options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user']
- options[:no_permission_check] = ENV['no_permission_check'] if ENV['no_permission_check']
- options[:no_account_notice] = ENV['no_account_notice'] if ENV['no_account_notice']
- options[:default_group] = ENV['default_group'] if ENV['default_group']
-
- Redmine::IMAP.check(imap_options, options)
- end
-
- desc <<-END_DESC
-Read emails from an POP3 server.
-
-Available POP3 options:
- host=HOST POP3 server host (default: 127.0.0.1)
- port=PORT POP3 server port (default: 110)
- username=USERNAME POP3 account
- password=PASSWORD POP3 password
- apop=1 use APOP authentication (default: false)
- delete_unprocessed=1 delete messages that could not be processed
- successfully from the server (default
- behaviour is to leave them on the server)
-
-See redmine:email:receive_imap for more options and examples.
-END_DESC
-
- task :receive_pop3 => :environment do
- pop_options = {:host => ENV['host'],
- :port => ENV['port'],
- :apop => ENV['apop'],
- :username => ENV['username'],
- :password => ENV['password'],
- :delete_unprocessed => ENV['delete_unprocessed']}
-
- options = { :issue => {} }
- %w(project status tracker category priority).each { |a| options[:issue][a.to_sym] = ENV[a] if ENV[a] }
- options[:allow_override] = ENV['allow_override'] if ENV['allow_override']
- options[:unknown_user] = ENV['unknown_user'] if ENV['unknown_user']
- options[:no_permission_check] = ENV['no_permission_check'] if ENV['no_permission_check']
- options[:no_account_notice] = ENV['no_account_notice'] if ENV['no_account_notice']
- options[:default_group] = ENV['default_group'] if ENV['default_group']
-
- Redmine::POP3.check(pop_options, options)
- end
-
- desc "Send a test email to the user with the provided login name"
- task :test, [:login] => :environment do |task, args|
- include Redmine::I18n
- abort l(:notice_email_error, "Please include the user login to test with. Example: rake redmine:email:test[login]") if args[:login].blank?
-
- user = User.find_by_login(args[:login])
- abort l(:notice_email_error, "User #{args[:login]} not found") unless user && user.logged?
-
- ActionMailer::Base.raise_delivery_errors = true
- begin
- Mailer.with_synched_deliveries do
- Mailer.test_email(user).deliver
- end
- puts l(:notice_email_sent, user.mail)
- rescue Exception => e
- abort l(:notice_email_error, e.message)
- end
- end
- end
-end
diff --git a/trustie2/lib/tasks/extract_fixtures.rake b/trustie2/lib/tasks/extract_fixtures.rake
deleted file mode 100644
index 65f529315..000000000
--- a/trustie2/lib/tasks/extract_fixtures.rake
+++ /dev/null
@@ -1,22 +0,0 @@
-desc 'Create YAML test fixtures from data in an existing database.
-Defaults to development database. Set RAILS_ENV to override.'
-
-task :extract_fixtures => :environment do
- sql = "SELECT * FROM %s"
- skip_tables = ["schema_info"]
- ActiveRecord::Base.establish_connection
- (ActiveRecord::Base.connection.tables - skip_tables).each do |table_name|
- i = "000"
- File.open("#{Rails.root}/#{table_name}.yml", 'w' ) do |file|
- data = ActiveRecord::Base.connection.select_all(sql % table_name)
- file.write data.inject({}) { |hash, record|
- # cast extracted values
- ActiveRecord::Base.connection.columns(table_name).each { |col|
- record[col.name] = col.type_cast(record[col.name]) if record[col.name]
- }
- hash["#{table_name}_#{i.succ!}"] = record
- hash
- }.to_yaml
- end
- end
-end
diff --git a/trustie2/lib/tasks/initializers.rake b/trustie2/lib/tasks/initializers.rake
deleted file mode 100644
index c1fdc7bf5..000000000
--- a/trustie2/lib/tasks/initializers.rake
+++ /dev/null
@@ -1,24 +0,0 @@
-desc 'Generates a secret token for the application.'
-
-file 'config/initializers/secret_token.rb' do
- path = File.join(Rails.root, 'config', 'initializers', 'secret_token.rb')
- secret = SecureRandom.hex(40)
- File.open(path, 'w') do |f|
- f.write <<"EOF"
-# This file was generated by 'rake generate_secret_token', and should
-# not be made visible to public.
-# If you have a load-balancing Redmine cluster, you will need to use the
-# same version of this file on each machine. And be sure to restart your
-# server when you modify this file.
-#
-# Your secret key for verifying cookie session data integrity. If you
-# change this key, all old sessions will become invalid! Make sure the
-# secret is at least 30 characters and all random, no regular words or
-# you'll be exposed to dictionary attacks.
-RedmineApp::Application.config.secret_token = '#{secret}'
-EOF
- end
-end
-
-desc 'Generates a secret token for the application.'
-task :generate_secret_token => ['config/initializers/secret_token.rb']
diff --git a/trustie2/lib/tasks/jdbc.rake b/trustie2/lib/tasks/jdbc.rake
deleted file mode 100644
index 289b3d94c..000000000
--- a/trustie2/lib/tasks/jdbc.rake
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was generated by the "jdbc" generator, which is provided
-# by the activerecord-jdbc-adapter gem.
-#
-# This file allows you to use Rails' various db:* tasks with JDBC.
-if defined?(JRUBY_VERSION)
- require 'jdbc_adapter'
- require 'jdbc_adapter/rake_tasks'
-end
diff --git a/trustie2/lib/tasks/load_default_data.rake b/trustie2/lib/tasks/load_default_data.rake
deleted file mode 100644
index cc6774bce..000000000
--- a/trustie2/lib/tasks/load_default_data.rake
+++ /dev/null
@@ -1,35 +0,0 @@
-desc 'Load Redmine default configuration data. Language is chosen interactively or by setting REDMINE_LANG environment variable.'
-
-namespace :redmine do
- task :load_default_data => :environment do
- include Redmine::I18n
- set_language_if_valid('en')
-
- envlang = ENV['REDMINE_LANG']
- if !envlang || !set_language_if_valid(envlang)
- puts
- while true
- print "Select language: "
- print valid_languages.collect(&:to_s).sort.join(", ")
- print " [#{current_language}] "
- STDOUT.flush
- lang = STDIN.gets.chomp!
- break if lang.empty?
- break if set_language_if_valid(lang)
- puts "Unknown language!"
- end
- STDOUT.flush
- puts "===================================="
- end
-
- begin
- Redmine::DefaultData::Loader.load(current_language)
- puts "Default configuration data loaded."
- rescue Redmine::DefaultData::DataAlreadyLoaded => error
- puts error.message
- rescue => error
- puts "Error: " + error.message
- puts "Default configuration data was not loaded."
- end
- end
-end
diff --git a/trustie2/lib/tasks/locales.rake b/trustie2/lib/tasks/locales.rake
deleted file mode 100644
index 6311d6ab1..000000000
--- a/trustie2/lib/tasks/locales.rake
+++ /dev/null
@@ -1,183 +0,0 @@
-desc 'Updates and checks locales against en.yml'
-task :locales do
- %w(locales:update locales:check_interpolation).collect do |task|
- Rake::Task[task].invoke
- end
-end
-
-namespace :locales do
- desc 'Updates language files based on en.yml content (only works for new top level keys).'
- task :update do
- dir = ENV['DIR'] || './config/locales'
-
- en_strings = YAML.load(File.read(File.join(dir,'en.yml')))['en']
-
- files = Dir.glob(File.join(dir,'*.{yaml,yml}'))
- files.sort.each do |file|
- puts "Updating file #{file}"
- file_strings = YAML.load(File.read(file))
- file_strings = file_strings[file_strings.keys.first]
-
- missing_keys = en_strings.keys - file_strings.keys
- next if missing_keys.empty?
-
- puts "==> Missing #{missing_keys.size} keys (#{missing_keys.join(', ')})"
- lang = File.open(file, 'a')
-
- missing_keys.each do |key|
- {key => en_strings[key]}.to_yaml.each_line do |line|
- next if line =~ /^---/ || line.empty?
- puts " #{line}"
- lang << " #{line}"
- end
- end
-
- lang.close
- end
- end
-
- desc 'Checks interpolation arguments in locals against en.yml'
- task :check_interpolation do
- dir = ENV['DIR'] || './config/locales'
- en_strings = YAML.load(File.read(File.join(dir,'en.yml')))['en']
- files = Dir.glob(File.join(dir,'*.{yaml,yml}'))
- files.sort.each do |file|
- puts "parsing #{file}..."
- file_strings = YAML.load_file(file)
- unless file_strings.is_a?(Hash)
- puts "#{file}: content is not a Hash (#{file_strings.class.name})"
- next
- end
- unless file_strings.keys.size == 1
- puts "#{file}: content has multiple keys (#{file_strings.keys.size})"
- next
- end
- file_strings = file_strings[file_strings.keys.first]
-
- file_strings.each do |key, string|
- next unless string.is_a?(String)
- string.scan /%\{\w+\}/ do |match|
- unless en_strings[key].nil? || en_strings[key].include?(match)
- puts "#{file}: #{key} uses #{match} not found in en.yml"
- end
- end
- end
- end
- end
-
- desc <<-END_DESC
-Removes a translation string from all locale file (only works for top-level childless non-multiline keys, probably doesn\'t work on windows).
-
-This task does not work on Ruby 1.8.6.
-You need to use Ruby 1.8.7 or later.
-
-Options:
- key=key_1,key_2 Comma-separated list of keys to delete
- skip=en,de Comma-separated list of locale files to ignore (filename without extension)
-END_DESC
-
- task :remove_key do
- dir = ENV['DIR'] || './config/locales'
- files = Dir.glob(File.join(dir,'*.yml'))
- skips = ENV['skip'] ? Regexp.union(ENV['skip'].split(',')) : nil
- deletes = ENV['key'] ? Regexp.union(ENV['key'].split(',')) : nil
- # Ignore multiline keys (begin with | or >) and keys with children (nothing meaningful after :)
- delete_regex = /\A #{deletes}: +[^\|>\s#].*\z/
-
- files.each do |path|
- # Skip certain locales
- (puts "Skipping #{path}"; next) if File.basename(path, ".yml") =~ skips
- puts "Deleting selected keys from #{path}"
- orig_content = File.open(path, 'r') {|file| file.read}
- File.open(path, 'w') {|file| orig_content.each_line {|line| file.puts line unless line.chomp =~ delete_regex}}
- end
- end
-
- desc <<-END_DESC
-Adds a new top-level translation string to all locale file (only works for childless keys, probably doesn\'t work on windows, doesn't check for duplicates).
-
-Options:
- key="some_key=foo"
- key1="another_key=bar"
- key_fb="foo=bar" Keys to add in the form key=value, every option of the form key[,\\d,_*] will be recognised
- skip=en,de Comma-separated list of locale files to ignore (filename without extension)
-END_DESC
-
- task :add_key do
- dir = ENV['DIR'] || './config/locales'
- files = Dir.glob(File.join(dir,'*.yml'))
- skips = ENV['skip'] ? Regexp.union(ENV['skip'].split(',')) : nil
- keys_regex = /\Akey(\d+|_.+)?\z/
- adds = ENV.reject {|k,v| !(k =~ keys_regex)}.values.collect {|v| Array.new v.split("=",2)}
- key_list = adds.collect {|v| v[0]}.join(", ")
-
- files.each do |path|
- # Skip certain locales
- (puts "Skipping #{path}"; next) if File.basename(path, ".yml") =~ skips
- # TODO: Check for dupliate/existing keys
- puts "Adding #{key_list} to #{path}"
- File.open(path, 'a') do |file|
- adds.each do |kv|
- Hash[*kv].to_yaml.each_line do |line|
- file.puts " #{line}" unless (line =~ /^---/ || line.empty?)
- end
- end
- end
- end
- end
-
- desc 'Duplicates a key. Exemple rake locales:dup key=foo new_key=bar'
- task :dup do
- dir = ENV['DIR'] || './config/locales'
- files = Dir.glob(File.join(dir,'*.yml'))
- skips = ENV['skip'] ? Regexp.union(ENV['skip'].split(',')) : nil
- key = ENV['key']
- new_key = ENV['new_key']
- abort "Missing key argument" if key.blank?
- abort "Missing new_key argument" if new_key.blank?
-
- files.each do |path|
- # Skip certain locales
- (puts "Skipping #{path}"; next) if File.basename(path, ".yml") =~ skips
- puts "Adding #{new_key} to #{path}"
-
- strings = File.read(path)
- unless strings =~ /^( #{key}: .+)$/
- puts "Key not found in #{path}"
- next
- end
- line = $1
-
- File.open(path, 'a') do |file|
- file.puts(line.sub(key, new_key))
- end
- end
- end
-
- desc 'Check parsing yaml by psych library on Ruby 1.9.'
-
- # On Fedora 12 and 13, if libyaml-devel is available,
- # in case of installing by rvm,
- # Ruby 1.9 default yaml library is psych.
-
- task :check_parsing_by_psych do
- begin
- require 'psych'
- parser = Psych::Parser.new
- dir = ENV['DIR'] || './config/locales'
- files = Dir.glob(File.join(dir,'*.yml'))
- files.sort.each do |filename|
- next if File.directory? filename
- puts "parsing #{filename}..."
- begin
- parser.parse File.open(filename)
- rescue Exception => e1
- puts(e1.message)
- puts("")
- end
- end
- rescue Exception => e
- puts(e.message)
- end
- end
-end
diff --git a/trustie2/lib/tasks/metrics.rake b/trustie2/lib/tasks/metrics.rake
deleted file mode 100644
index 214cc996e..000000000
--- a/trustie2/lib/tasks/metrics.rake
+++ /dev/null
@@ -1,6 +0,0 @@
-begin
- require 'metric_fu'
-rescue LoadError
- # Metric-fu not installed
- # http://metric-fu.rubyforge.org/
-end
diff --git a/trustie2/lib/tasks/migrate_from_mantis.rake b/trustie2/lib/tasks/migrate_from_mantis.rake
deleted file mode 100644
index b5a061ca3..000000000
--- a/trustie2/lib/tasks/migrate_from_mantis.rake
+++ /dev/null
@@ -1,512 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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.
-
-desc 'Mantis migration script'
-
-require 'active_record'
-require 'iconv' if RUBY_VERSION < '1.9'
-require 'pp'
-
-namespace :redmine do
-task :migrate_from_mantis => :environment do
-
- module MantisMigrate
-
- DEFAULT_STATUS = IssueStatus.default
- assigned_status = IssueStatus.find_by_position(2)
- resolved_status = IssueStatus.find_by_position(3)
- feedback_status = IssueStatus.find_by_position(4)
- closed_status = IssueStatus.where(:is_closed => true).first
- STATUS_MAPPING = {10 => DEFAULT_STATUS, # new
- 20 => feedback_status, # feedback
- 30 => DEFAULT_STATUS, # acknowledged
- 40 => DEFAULT_STATUS, # confirmed
- 50 => assigned_status, # assigned
- 80 => resolved_status, # resolved
- 90 => closed_status # closed
- }
-
- priorities = IssuePriority.all
- DEFAULT_PRIORITY = priorities[2]
- PRIORITY_MAPPING = {10 => priorities[1], # none
- 20 => priorities[1], # low
- 30 => priorities[2], # normal
- 40 => priorities[3], # high
- 50 => priorities[4], # urgent
- 60 => priorities[5] # immediate
- }
-
- TRACKER_BUG = Tracker.find_by_position(1)
- TRACKER_FEATURE = Tracker.find_by_position(2)
-
- roles = Role.where(:builtin => 0).order('position ASC').all
- manager_role = roles[0]
- developer_role = roles[1]
- DEFAULT_ROLE = roles.last
- ROLE_MAPPING = {10 => DEFAULT_ROLE, # viewer
- 25 => DEFAULT_ROLE, # reporter
- 40 => DEFAULT_ROLE, # updater
- 55 => developer_role, # developer
- 70 => manager_role, # manager
- 90 => manager_role # administrator
- }
-
- CUSTOM_FIELD_TYPE_MAPPING = {0 => 'string', # String
- 1 => 'int', # Numeric
- 2 => 'int', # Float
- 3 => 'list', # Enumeration
- 4 => 'string', # Email
- 5 => 'bool', # Checkbox
- 6 => 'list', # List
- 7 => 'list', # Multiselection list
- 8 => 'date', # Date
- }
-
- RELATION_TYPE_MAPPING = {1 => IssueRelation::TYPE_RELATES, # related to
- 2 => IssueRelation::TYPE_RELATES, # parent of
- 3 => IssueRelation::TYPE_RELATES, # child of
- 0 => IssueRelation::TYPE_DUPLICATES, # duplicate of
- 4 => IssueRelation::TYPE_DUPLICATES # has duplicate
- }
-
- class MantisUser < ActiveRecord::Base
- self.table_name = :mantis_user_table
-
- def firstname
- @firstname = realname.blank? ? username : realname.split.first[0..29]
- @firstname
- end
-
- def lastname
- @lastname = realname.blank? ? '-' : realname.split[1..-1].join(' ')[0..29]
- @lastname = '-' if @lastname.blank?
- @lastname
- end
-
- def email
- if read_attribute(:email).match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) &&
- !User.find_by_mail(read_attribute(:email))
- @email = read_attribute(:email)
- else
- @email = "#{username}@foo.bar"
- end
- end
-
- def username
- read_attribute(:username)[0..29].gsub(/[^a-zA-Z0-9_\-@\.]/, '-')
- end
- end
-
- class MantisProject < ActiveRecord::Base
- self.table_name = :mantis_project_table
- has_many :versions, :class_name => "MantisVersion", :foreign_key => :project_id
- has_many :categories, :class_name => "MantisCategory", :foreign_key => :project_id
- has_many :news, :class_name => "MantisNews", :foreign_key => :project_id
- has_many :members, :class_name => "MantisProjectUser", :foreign_key => :project_id
-
- def identifier
- read_attribute(:name).gsub(/[^a-z0-9\-]+/, '-').slice(0, Project::IDENTIFIER_MAX_LENGTH)
- end
- end
-
- class MantisVersion < ActiveRecord::Base
- self.table_name = :mantis_project_version_table
-
- def version
- read_attribute(:version)[0..29]
- end
-
- def description
- read_attribute(:description)[0..254]
- end
- end
-
- class MantisCategory < ActiveRecord::Base
- self.table_name = :mantis_project_category_table
- end
-
- class MantisProjectUser < ActiveRecord::Base
- self.table_name = :mantis_project_user_list_table
- end
-
- class MantisBug < ActiveRecord::Base
- self.table_name = :mantis_bug_table
- belongs_to :bug_text, :class_name => "MantisBugText", :foreign_key => :bug_text_id
- has_many :bug_notes, :class_name => "MantisBugNote", :foreign_key => :bug_id
- has_many :bug_files, :class_name => "MantisBugFile", :foreign_key => :bug_id
- has_many :bug_monitors, :class_name => "MantisBugMonitor", :foreign_key => :bug_id
- end
-
- class MantisBugText < ActiveRecord::Base
- self.table_name = :mantis_bug_text_table
-
- # Adds Mantis steps_to_reproduce and additional_information fields
- # to description if any
- def full_description
- full_description = description
- full_description += "\n\n*Steps to reproduce:*\n\n#{steps_to_reproduce}" unless steps_to_reproduce.blank?
- full_description += "\n\n*Additional information:*\n\n#{additional_information}" unless additional_information.blank?
- full_description
- end
- end
-
- class MantisBugNote < ActiveRecord::Base
- self.table_name = :mantis_bugnote_table
- belongs_to :bug, :class_name => "MantisBug", :foreign_key => :bug_id
- belongs_to :bug_note_text, :class_name => "MantisBugNoteText", :foreign_key => :bugnote_text_id
- end
-
- class MantisBugNoteText < ActiveRecord::Base
- self.table_name = :mantis_bugnote_text_table
- end
-
- class MantisBugFile < ActiveRecord::Base
- self.table_name = :mantis_bug_file_table
-
- def size
- filesize
- end
-
- def original_filename
- MantisMigrate.encode(filename)
- end
-
- def content_type
- file_type
- end
-
- def read(*args)
- if @read_finished
- nil
- else
- @read_finished = true
- content
- end
- end
- end
-
- class MantisBugRelationship < ActiveRecord::Base
- self.table_name = :mantis_bug_relationship_table
- end
-
- class MantisBugMonitor < ActiveRecord::Base
- self.table_name = :mantis_bug_monitor_table
- end
-
- class MantisNews < ActiveRecord::Base
- self.table_name = :mantis_news_table
- end
-
- class MantisCustomField < ActiveRecord::Base
- self.table_name = :mantis_custom_field_table
- set_inheritance_column :none
- has_many :values, :class_name => "MantisCustomFieldString", :foreign_key => :field_id
- has_many :projects, :class_name => "MantisCustomFieldProject", :foreign_key => :field_id
-
- def format
- read_attribute :type
- end
-
- def name
- read_attribute(:name)[0..29]
- end
- end
-
- class MantisCustomFieldProject < ActiveRecord::Base
- self.table_name = :mantis_custom_field_project_table
- end
-
- class MantisCustomFieldString < ActiveRecord::Base
- self.table_name = :mantis_custom_field_string_table
- end
-
- def self.migrate
-
- # Users
- print "Migrating users"
- User.delete_all "login <> 'admin'"
- users_map = {}
- users_migrated = 0
- MantisUser.all.each do |user|
- u = User.new :firstname => encode(user.firstname),
- :lastname => encode(user.lastname),
- :mail => user.email,
- :last_login_on => user.last_visit
- u.login = user.username
- u.password = 'mantis'
- u.status = User::STATUS_LOCKED if user.enabled != 1
- u.admin = true if user.access_level == 90
- next unless u.save!
- users_migrated += 1
- users_map[user.id] = u.id
- print '.'
- end
- puts
-
- # Projects
- print "Migrating projects"
- Project.destroy_all
- projects_map = {}
- versions_map = {}
- categories_map = {}
- MantisProject.all.each do |project|
- p = Project.new :name => encode(project.name),
- :description => encode(project.description)
- p.identifier = project.identifier
- next unless p.save
- projects_map[project.id] = p.id
- p.enabled_module_names = ['issue_tracking', 'news', 'wiki']
- p.trackers << TRACKER_BUG unless p.trackers.include?(TRACKER_BUG)
- p.trackers << TRACKER_FEATURE unless p.trackers.include?(TRACKER_FEATURE)
- print '.'
-
- # Project members
- project.members.each do |member|
- m = Member.new :user => User.find_by_id(users_map[member.user_id]),
- :roles => [ROLE_MAPPING[member.access_level] || DEFAULT_ROLE]
- m.project = p
- m.save
- end
-
- # Project versions
- project.versions.each do |version|
- v = Version.new :name => encode(version.version),
- :description => encode(version.description),
- :effective_date => (version.date_order ? version.date_order.to_date : nil)
- v.project = p
- v.save
- versions_map[version.id] = v.id
- end
-
- # Project categories
- project.categories.each do |category|
- g = IssueCategory.new :name => category.category[0,30]
- g.project = p
- g.save
- categories_map[category.category] = g.id
- end
- end
- puts
-
- # Bugs
- print "Migrating bugs"
- Issue.destroy_all
- issues_map = {}
- keep_bug_ids = (Issue.count == 0)
- MantisBug.find_each(:batch_size => 200) do |bug|
- next unless projects_map[bug.project_id] && users_map[bug.reporter_id]
- i = Issue.new :project_id => projects_map[bug.project_id],
- :title => encode(bug.summary),
- :description => encode(bug.bug_text.full_description),
- :priority => PRIORITY_MAPPING[bug.priority] || DEFAULT_PRIORITY,
- :created_on => bug.date_submitted,
- :updated_on => bug.last_updated
- i.author = User.find_by_id(users_map[bug.reporter_id])
- i.category = IssueCategory.find_by_project_id_and_name(i.project_id, bug.category[0,30]) unless bug.category.blank?
- i.fixed_version = Version.find_by_project_id_and_name(i.project_id, bug.fixed_in_version) unless bug.fixed_in_version.blank?
- i.status = STATUS_MAPPING[bug.status] || DEFAULT_STATUS
- i.tracker = (bug.severity == 10 ? TRACKER_FEATURE : TRACKER_BUG)
- i.id = bug.id if keep_bug_ids
- next unless i.save
- issues_map[bug.id] = i.id
- print '.'
- STDOUT.flush
-
- # Assignee
- # Redmine checks that the assignee is a project member
- if (bug.handler_id && users_map[bug.handler_id])
- i.assigned_to = User.find_by_id(users_map[bug.handler_id])
- i.save(:validate => false)
- end
-
- # Bug notes
- bug.bug_notes.each do |note|
- next unless users_map[note.reporter_id]
- n = Journal.new :notes => encode(note.bug_note_text.note),
- :created_on => note.date_submitted
- n.user = User.find_by_id(users_map[note.reporter_id])
- n.journalized = i
- n.save
- end
-
- # Bug files
- bug.bug_files.each do |file|
- a = Attachment.new :created_on => file.date_added
- a.file = file
- a.author = User.first
- a.container = i
- a.save
- end
-
- # Bug monitors
- bug.bug_monitors.each do |monitor|
- next unless users_map[monitor.user_id]
- i.add_watcher(User.find_by_id(users_map[monitor.user_id]))
- end
- end
-
- # update issue id sequence if needed (postgresql)
- Issue.connection.reset_pk_sequence!(Issue.table_name) if Issue.connection.respond_to?('reset_pk_sequence!')
- puts
-
- # Bug relationships
- print "Migrating bug relations"
- MantisBugRelationship.all.each do |relation|
- next unless issues_map[relation.source_bug_id] && issues_map[relation.destination_bug_id]
- r = IssueRelation.new :relation_type => RELATION_TYPE_MAPPING[relation.relationship_type]
- r.issue_from = Issue.find_by_id(issues_map[relation.source_bug_id])
- r.issue_to = Issue.find_by_id(issues_map[relation.destination_bug_id])
- pp r unless r.save
- print '.'
- STDOUT.flush
- end
- puts
-
- # News
- print "Migrating news"
- News.destroy_all
- MantisNews.where('project_id > 0').all.each do |news|
- next unless projects_map[news.project_id]
- n = News.new :project_id => projects_map[news.project_id],
- :title => encode(news.headline[0..59]),
- :description => encode(news.body),
- :created_on => news.date_posted
- n.author = User.find_by_id(users_map[news.poster_id])
- n.save
- print '.'
- STDOUT.flush
- end
- puts
-
- # Custom fields
- print "Migrating custom fields"
- IssueCustomField.destroy_all
- MantisCustomField.all.each do |field|
- f = IssueCustomField.new :name => field.name[0..29],
- :field_format => CUSTOM_FIELD_TYPE_MAPPING[field.format],
- :min_length => field.length_min,
- :max_length => field.length_max,
- :regexp => field.valid_regexp,
- :possible_values => field.possible_values.split('|'),
- :is_required => field.require_report?
- next unless f.save
- print '.'
- STDOUT.flush
- # Trackers association
- f.trackers = Tracker.all
-
- # Projects association
- field.projects.each do |project|
- f.projects << Project.find_by_id(projects_map[project.project_id]) if projects_map[project.project_id]
- end
-
- # Values
- field.values.each do |value|
- v = CustomValue.new :custom_field_id => f.id,
- :value => value.value
- v.customized = Issue.find_by_id(issues_map[value.bug_id]) if issues_map[value.bug_id]
- v.save
- end unless f.new_record?
- end
- puts
-
- puts
- puts "Users: #{users_migrated}/#{MantisUser.count}"
- puts "Projects: #{Project.count}/#{MantisProject.count}"
- puts "Memberships: #{Member.count}/#{MantisProjectUser.count}"
- puts "Versions: #{Version.count}/#{MantisVersion.count}"
- puts "Categories: #{IssueCategory.count}/#{MantisCategory.count}"
- puts "Bugs: #{Issue.count}/#{MantisBug.count}"
- puts "Bug notes: #{Journal.count}/#{MantisBugNote.count}"
- puts "Bug files: #{Attachment.count}/#{MantisBugFile.count}"
- puts "Bug relations: #{IssueRelation.count}/#{MantisBugRelationship.count}"
- puts "Bug monitors: #{Watcher.count}/#{MantisBugMonitor.count}"
- puts "News: #{News.count}/#{MantisNews.count}"
- puts "Custom fields: #{IssueCustomField.count}/#{MantisCustomField.count}"
- end
-
- def self.encoding(charset)
- @charset = charset
- end
-
- def self.establish_connection(params)
- constants.each do |const|
- klass = const_get(const)
- next unless klass.respond_to? 'establish_connection'
- klass.establish_connection params
- end
- end
-
- def self.encode(text)
- if RUBY_VERSION < '1.9'
- @ic ||= Iconv.new('UTF-8', @charset)
- @ic.iconv text
- else
- text.to_s.force_encoding(@charset).encode('UTF-8')
- end
- end
- end
-
- puts
- if Redmine::DefaultData::Loader.no_data?
- puts "Redmine configuration need to be loaded before importing data."
- puts "Please, run this first:"
- puts
- puts " rake redmine:load_default_data RAILS_ENV=\"#{ENV['RAILS_ENV']}\""
- exit
- end
-
- puts "WARNING: Your Redmine data will be deleted during this process."
- print "Are you sure you want to continue ? [y/N] "
- STDOUT.flush
- break unless STDIN.gets.match(/^y$/i)
-
- # Default Mantis database settings
- db_params = {:adapter => 'mysql2',
- :database => 'bugtracker',
- :host => 'localhost',
- :username => 'root',
- :password => '' }
-
- puts
- puts "Please enter settings for your Mantis database"
- [:adapter, :host, :database, :username, :password].each do |param|
- print "#{param} [#{db_params[param]}]: "
- value = STDIN.gets.chomp!
- db_params[param] = value unless value.blank?
- end
-
- while true
- print "encoding [UTF-8]: "
- STDOUT.flush
- encoding = STDIN.gets.chomp!
- encoding = 'UTF-8' if encoding.blank?
- break if MantisMigrate.encoding encoding
- puts "Invalid encoding!"
- end
- puts
-
- # Make sure bugs can refer bugs in other projects
- Setting.cross_project_issue_relations = 1 if Setting.respond_to? 'cross_project_issue_relations'
-
- # Turn off email notifications
- Setting.notified_events = []
-
- MantisMigrate.establish_connection db_params
- MantisMigrate.migrate
-end
-end
diff --git a/trustie2/lib/tasks/migrate_from_trac.rake b/trustie2/lib/tasks/migrate_from_trac.rake
deleted file mode 100644
index 58ed61f46..000000000
--- a/trustie2/lib/tasks/migrate_from_trac.rake
+++ /dev/null
@@ -1,771 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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 'active_record'
-require 'iconv' if RUBY_VERSION < '1.9'
-require 'pp'
-
-namespace :redmine do
- desc 'Trac migration script'
- task :migrate_from_trac => :environment do
-
- module TracMigrate
- TICKET_MAP = []
-
- DEFAULT_STATUS = IssueStatus.default
- assigned_status = IssueStatus.find_by_position(2)
- resolved_status = IssueStatus.find_by_position(3)
- feedback_status = IssueStatus.find_by_position(4)
- closed_status = IssueStatus.where(:is_closed => true).first
- STATUS_MAPPING = {'new' => DEFAULT_STATUS,
- 'reopened' => feedback_status,
- 'assigned' => assigned_status,
- 'closed' => closed_status
- }
-
- priorities = IssuePriority.all
- DEFAULT_PRIORITY = priorities[0]
- PRIORITY_MAPPING = {'lowest' => priorities[0],
- 'low' => priorities[0],
- 'normal' => priorities[1],
- 'high' => priorities[2],
- 'highest' => priorities[3],
- # ---
- 'trivial' => priorities[0],
- 'minor' => priorities[1],
- 'major' => priorities[2],
- 'critical' => priorities[3],
- 'blocker' => priorities[4]
- }
-
- TRACKER_BUG = Tracker.find_by_position(1)
- TRACKER_FEATURE = Tracker.find_by_position(2)
- DEFAULT_TRACKER = TRACKER_BUG
- TRACKER_MAPPING = {'defect' => TRACKER_BUG,
- 'enhancement' => TRACKER_FEATURE,
- 'task' => TRACKER_FEATURE,
- 'patch' =>TRACKER_FEATURE
- }
-
- roles = Role.where(:builtin => 0).order('position ASC').all
- manager_role = roles[0]
- developer_role = roles[1]
- DEFAULT_ROLE = roles.last
- ROLE_MAPPING = {'admin' => manager_role,
- 'developer' => developer_role
- }
-
- class ::Time
- class << self
- alias :real_now :now
- def now
- real_now - @fake_diff.to_i
- end
- def fake(time)
- @fake_diff = real_now - time
- res = yield
- @fake_diff = 0
- res
- end
- end
- end
-
- class TracComponent < ActiveRecord::Base
- self.table_name = :component
- end
-
- class TracMilestone < ActiveRecord::Base
- self.table_name = :milestone
- # If this attribute is set a milestone has a defined target timepoint
- def due
- if read_attribute(:due) && read_attribute(:due) > 0
- Time.at(read_attribute(:due)).to_date
- else
- nil
- end
- end
- # This is the real timepoint at which the milestone has finished.
- def completed
- if read_attribute(:completed) && read_attribute(:completed) > 0
- Time.at(read_attribute(:completed)).to_date
- else
- nil
- end
- end
-
- def description
- # Attribute is named descr in Trac v0.8.x
- has_attribute?(:descr) ? read_attribute(:descr) : read_attribute(:description)
- end
- end
-
- class TracTicketCustom < ActiveRecord::Base
- self.table_name = :ticket_custom
- end
-
- class TracAttachment < ActiveRecord::Base
- self.table_name = :attachment
- set_inheritance_column :none
-
- def time; Time.at(read_attribute(:time)) end
-
- def original_filename
- filename
- end
-
- def content_type
- ''
- end
-
- def exist?
- File.file? trac_fullpath
- end
-
- def open
- File.open("#{trac_fullpath}", 'rb') {|f|
- @file = f
- yield self
- }
- end
-
- def read(*args)
- @file.read(*args)
- end
-
- def description
- read_attribute(:description).to_s.slice(0,255)
- end
-
- private
- def trac_fullpath
- attachment_type = read_attribute(:type)
- trac_file = filename.gsub( /[^a-zA-Z0-9\-_\.!~*']/n ) {|x| sprintf('%%%02x', x[0]) }
- "#{TracMigrate.trac_attachments_directory}/#{attachment_type}/#{id}/#{trac_file}"
- end
- end
-
- class TracTicket < ActiveRecord::Base
- self.table_name = :ticket
- set_inheritance_column :none
-
- # ticket changes: only migrate status changes and comments
- has_many :ticket_changes, :class_name => "TracTicketChange", :foreign_key => :ticket
- has_many :customs, :class_name => "TracTicketCustom", :foreign_key => :ticket
-
- def attachments
- TracMigrate::TracAttachment.all(:conditions => ["type = 'ticket' AND id = ?", self.id.to_s])
- end
-
- def ticket_type
- read_attribute(:type)
- end
-
- def summary
- read_attribute(:summary).blank? ? "(no title)" : read_attribute(:summary)
- end
-
- def description
- read_attribute(:description).blank? ? summary : read_attribute(:description)
- end
-
- def time; Time.at(read_attribute(:time)) end
- def changetime; Time.at(read_attribute(:changetime)) end
- end
-
- class TracTicketChange < ActiveRecord::Base
- self.table_name = :ticket_change
-
- def self.columns
- # Hides Trac field 'field' to prevent clash with AR field_changed? method (Rails 3.0)
- super.select {|column| column.name.to_s != 'field'}
- end
-
- def time; Time.at(read_attribute(:time)) end
- end
-
- TRAC_WIKI_PAGES = %w(InterMapTxt InterTrac InterWiki RecentChanges SandBox TracAccessibility TracAdmin TracBackup TracBrowser TracCgi TracChangeset \
- TracEnvironment TracFastCgi TracGuide TracImport TracIni TracInstall TracInterfaceCustomization \
- TracLinks TracLogging TracModPython TracNotification TracPermissions TracPlugins TracQuery \
- TracReports TracRevisionLog TracRoadmap TracRss TracSearch TracStandalone TracSupport TracSyntaxColoring TracTickets \
- TracTicketsCustomFields TracTimeline TracUnicode TracUpgrade TracWiki WikiDeletePage WikiFormatting \
- WikiHtml WikiMacros WikiNewPage WikiPageNames WikiProcessors WikiRestructuredText WikiRestructuredTextLinks \
- CamelCase TitleIndex)
-
- class TracWikiPage < ActiveRecord::Base
- self.table_name = :wiki
- set_primary_key :name
-
- def self.columns
- # Hides readonly Trac field to prevent clash with AR readonly? method (Rails 2.0)
- super.select {|column| column.name.to_s != 'readonly'}
- end
-
- def attachments
- TracMigrate::TracAttachment.all(:conditions => ["type = 'wiki' AND id = ?", self.id.to_s])
- end
-
- def time; Time.at(read_attribute(:time)) end
- end
-
- class TracPermission < ActiveRecord::Base
- self.table_name = :permission
- end
-
- class TracSessionAttribute < ActiveRecord::Base
- self.table_name = :session_attribute
- end
-
- def self.find_or_create_user(username, project_member = false)
- return User.anonymous if username.blank?
-
- u = User.find_by_login(username)
- if !u
- # Create a new user if not found
- mail = username[0, User::MAIL_LENGTH_LIMIT]
- if mail_attr = TracSessionAttribute.find_by_sid_and_name(username, 'email')
- mail = mail_attr.value
- end
- mail = "#{mail}@foo.bar" unless mail.include?("@")
-
- name = username
- if name_attr = TracSessionAttribute.find_by_sid_and_name(username, 'name')
- name = name_attr.value
- end
- name =~ (/(.*)(\s+\w+)?/)
- fn = $1.strip
- ln = ($2 || '-').strip
-
- u = User.new :mail => mail.gsub(/[^-@a-z0-9\.]/i, '-'),
- :firstname => fn[0, limit_for(User, 'firstname')],
- :lastname => ln[0, limit_for(User, 'lastname')]
-
- u.login = username[0, User::LOGIN_LENGTH_LIMIT].gsub(/[^a-z0-9_\-@\.]/i, '-')
- u.password = 'trac'
- u.admin = true if TracPermission.find_by_username_and_action(username, 'admin')
- # finally, a default user is used if the new user is not valid
- u = User.first unless u.save
- end
- # Make sure he is a member of the project
- if project_member && !u.member_of?(@target_project)
- role = DEFAULT_ROLE
- if u.admin
- role = ROLE_MAPPING['admin']
- elsif TracPermission.find_by_username_and_action(username, 'developer')
- role = ROLE_MAPPING['developer']
- end
- Member.create(:user => u, :project => @target_project, :roles => [role])
- u.reload
- end
- u
- end
-
- # Basic wiki syntax conversion
- def self.convert_wiki_text(text)
- # Titles
- text = text.gsub(/^(\=+)\s(.+)\s(\=+)/) {|s| "\nh#{$1.length}. #{$2}\n"}
- # External Links
- text = text.gsub(/\[(http[^\s]+)\s+([^\]]+)\]/) {|s| "\"#{$2}\":#{$1}"}
- # Ticket links:
- # [ticket:234 Text],[ticket:234 This is a test]
- text = text.gsub(/\[ticket\:([^\ ]+)\ (.+?)\]/, '"\2":/issues/show/\1')
- # ticket:1234
- # #1 is working cause Redmine uses the same syntax.
- text = text.gsub(/ticket\:([^\ ]+)/, '#\1')
- # Milestone links:
- # [milestone:"0.1.0 Mercury" Milestone 0.1.0 (Mercury)]
- # The text "Milestone 0.1.0 (Mercury)" is not converted,
- # cause Redmine's wiki does not support this.
- text = text.gsub(/\[milestone\:\"([^\"]+)\"\ (.+?)\]/, 'version:"\1"')
- # [milestone:"0.1.0 Mercury"]
- text = text.gsub(/\[milestone\:\"([^\"]+)\"\]/, 'version:"\1"')
- text = text.gsub(/milestone\:\"([^\"]+)\"/, 'version:"\1"')
- # milestone:0.1.0
- text = text.gsub(/\[milestone\:([^\ ]+)\]/, 'version:\1')
- text = text.gsub(/milestone\:([^\ ]+)/, 'version:\1')
- # Internal Links
- text = text.gsub(/\[\[BR\]\]/, "\n") # This has to go before the rules below
- text = text.gsub(/\[\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
- text = text.gsub(/\[wiki:\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
- text = text.gsub(/\[wiki:\"(.+)\".*\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
- text = text.gsub(/\[wiki:([^\s\]]+)\]/) {|s| "[[#{$1.delete(',./?;|:')}]]"}
- text = text.gsub(/\[wiki:([^\s\]]+)\s(.*)\]/) {|s| "[[#{$1.delete(',./?;|:')}|#{$2.delete(',./?;|:')}]]"}
-
- # Links to pages UsingJustWikiCaps
- text = text.gsub(/([^!]|^)(^| )([A-Z][a-z]+[A-Z][a-zA-Z]+)/, '\\1\\2[[\3]]')
- # Normalize things that were supposed to not be links
- # like !NotALink
- text = text.gsub(/(^| )!([A-Z][A-Za-z]+)/, '\1\2')
- # Revisions links
- text = text.gsub(/\[(\d+)\]/, 'r\1')
- # Ticket number re-writing
- text = text.gsub(/#(\d+)/) do |s|
- if $1.length < 10
-# TICKET_MAP[$1.to_i] ||= $1
- "\##{TICKET_MAP[$1.to_i] || $1}"
- else
- s
- end
- end
- # We would like to convert the Code highlighting too
- # This will go into the next line.
- shebang_line = false
- # Reguar expression for start of code
- pre_re = /\{\{\{/
- # Code hightlighing...
- shebang_re = /^\#\!([a-z]+)/
- # Regular expression for end of code
- pre_end_re = /\}\}\}/
-
- # Go through the whole text..extract it line by line
- text = text.gsub(/^(.*)$/) do |line|
- m_pre = pre_re.match(line)
- if m_pre
- line = '
'
- else
- m_sl = shebang_re.match(line)
- if m_sl
- shebang_line = true
- line = ''
- end
- m_pre_end = pre_end_re.match(line)
- if m_pre_end
- line = '
'
- if shebang_line
- line = '' + line
- end
- end
- end
- line
- end
-
- # Highlighting
- text = text.gsub(/'''''([^\s])/, '_*\1')
- text = text.gsub(/([^\s])'''''/, '\1*_')
- text = text.gsub(/'''/, '*')
- text = text.gsub(/''/, '_')
- text = text.gsub(/__/, '+')
- text = text.gsub(/~~/, '-')
- text = text.gsub(/`/, '@')
- text = text.gsub(/,,/, '~')
- # Lists
- text = text.gsub(/^([ ]+)\* /) {|s| '*' * $1.length + " "}
-
- text
- end
-
- def self.migrate
- establish_connection
-
- # Quick database test
- TracComponent.count
-
- migrated_components = 0
- migrated_milestones = 0
- migrated_tickets = 0
- migrated_custom_values = 0
- migrated_ticket_attachments = 0
- migrated_wiki_edits = 0
- migrated_wiki_attachments = 0
-
- #Wiki system initializing...
- @target_project.wiki.destroy if @target_project.wiki
- @target_project.reload
- wiki = Wiki.new(:project => @target_project, :start_page => 'WikiStart')
- wiki_edit_count = 0
-
- # Components
- print "Migrating components"
- issues_category_map = {}
- TracComponent.all.each do |component|
- print '.'
- STDOUT.flush
- c = IssueCategory.new :project => @target_project,
- :name => encode(component.name[0, limit_for(IssueCategory, 'name')])
- next unless c.save
- issues_category_map[component.name] = c
- migrated_components += 1
- end
- puts
-
- # Milestones
- print "Migrating milestones"
- version_map = {}
- TracMilestone.all.each do |milestone|
- print '.'
- STDOUT.flush
- # First we try to find the wiki page...
- p = wiki.find_or_new_page(milestone.name.to_s)
- p.content = WikiContent.new(:page => p) if p.new_record?
- p.content.text = milestone.description.to_s
- p.content.author = find_or_create_user('trac')
- p.content.comments = 'Milestone'
- p.save
-
- v = Version.new :project => @target_project,
- :name => encode(milestone.name[0, limit_for(Version, 'name')]),
- :description => nil,
- :wiki_page_title => milestone.name.to_s,
- :effective_date => milestone.completed
-
- next unless v.save
- version_map[milestone.name] = v
- migrated_milestones += 1
- end
- puts
-
- # Custom fields
- # TODO: read trac.ini instead
- print "Migrating custom fields"
- custom_field_map = {}
- TracTicketCustom.find_by_sql("SELECT DISTINCT name FROM #{TracTicketCustom.table_name}").each do |field|
- print '.'
- STDOUT.flush
- # Redmine custom field name
- field_name = encode(field.name[0, limit_for(IssueCustomField, 'name')]).humanize
- # Find if the custom already exists in Redmine
- f = IssueCustomField.find_by_name(field_name)
- # Or create a new one
- f ||= IssueCustomField.create(:name => encode(field.name[0, limit_for(IssueCustomField, 'name')]).humanize,
- :field_format => 'string')
-
- next if f.new_record?
- f.trackers = Tracker.all
- f.projects << @target_project
- custom_field_map[field.name] = f
- end
- puts
-
- # Trac 'resolution' field as a Redmine custom field
- r = IssueCustomField.where(:name => "Resolution").first
- r = IssueCustomField.new(:name => 'Resolution',
- :field_format => 'list',
- :is_filter => true) if r.nil?
- r.trackers = Tracker.all
- r.projects << @target_project
- r.possible_values = (r.possible_values + %w(fixed invalid wontfix duplicate worksforme)).flatten.compact.uniq
- r.save!
- custom_field_map['resolution'] = r
-
- # Tickets
- print "Migrating tickets"
- TracTicket.find_each(:batch_size => 200) do |ticket|
- print '.'
- STDOUT.flush
- i = Issue.new :project => @target_project,
- :title => encode(ticket.summary[0, limit_for(Issue, 'title')]),
- :description => convert_wiki_text(encode(ticket.description)),
- :priority => PRIORITY_MAPPING[ticket.priority] || DEFAULT_PRIORITY,
- :created_on => ticket.time
- i.author = find_or_create_user(ticket.reporter)
- i.category = issues_category_map[ticket.component] unless ticket.component.blank?
- i.fixed_version = version_map[ticket.milestone] unless ticket.milestone.blank?
- i.status = STATUS_MAPPING[ticket.status] || DEFAULT_STATUS
- i.tracker = TRACKER_MAPPING[ticket.ticket_type] || DEFAULT_TRACKER
- i.id = ticket.id unless Issue.exists?(ticket.id)
- next unless Time.fake(ticket.changetime) { i.save }
- TICKET_MAP[ticket.id] = i.id
- migrated_tickets += 1
-
- # Owner
- unless ticket.owner.blank?
- i.assigned_to = find_or_create_user(ticket.owner, true)
- Time.fake(ticket.changetime) { i.save }
- end
-
- # Comments and status/resolution changes
- ticket.ticket_changes.group_by(&:time).each do |time, changeset|
- status_change = changeset.select {|change| change.field == 'status'}.first
- resolution_change = changeset.select {|change| change.field == 'resolution'}.first
- comment_change = changeset.select {|change| change.field == 'comment'}.first
-
- n = Journal.new :notes => (comment_change ? convert_wiki_text(encode(comment_change.newvalue)) : ''),
- :created_on => time
- n.user = find_or_create_user(changeset.first.author)
- n.journalized = i
- if status_change &&
- STATUS_MAPPING[status_change.oldvalue] &&
- STATUS_MAPPING[status_change.newvalue] &&
- (STATUS_MAPPING[status_change.oldvalue] != STATUS_MAPPING[status_change.newvalue])
- n.details << JournalDetail.new(:property => 'attr',
- :prop_key => 'status_id',
- :old_value => STATUS_MAPPING[status_change.oldvalue].id,
- :value => STATUS_MAPPING[status_change.newvalue].id)
- end
- if resolution_change
- n.details << JournalDetail.new(:property => 'cf',
- :prop_key => custom_field_map['resolution'].id,
- :old_value => resolution_change.oldvalue,
- :value => resolution_change.newvalue)
- end
- n.save unless n.details.empty? && n.notes.blank?
- end
-
- # Attachments
- ticket.attachments.each do |attachment|
- next unless attachment.exist?
- attachment.open {
- a = Attachment.new :created_on => attachment.time
- a.file = attachment
- a.author = find_or_create_user(attachment.author)
- a.container = i
- a.description = attachment.description
- migrated_ticket_attachments += 1 if a.save
- }
- end
-
- # Custom fields
- custom_values = ticket.customs.inject({}) do |h, custom|
- if custom_field = custom_field_map[custom.name]
- h[custom_field.id] = custom.value
- migrated_custom_values += 1
- end
- h
- end
- if custom_field_map['resolution'] && !ticket.resolution.blank?
- custom_values[custom_field_map['resolution'].id] = ticket.resolution
- end
- i.custom_field_values = custom_values
- i.save_custom_field_values
- end
-
- # update issue id sequence if needed (postgresql)
- Issue.connection.reset_pk_sequence!(Issue.table_name) if Issue.connection.respond_to?('reset_pk_sequence!')
- puts
-
- # Wiki
- print "Migrating wiki"
- if wiki.save
- TracWikiPage.order('name, version').all.each do |page|
- # Do not migrate Trac manual wiki pages
- next if TRAC_WIKI_PAGES.include?(page.name)
- wiki_edit_count += 1
- print '.'
- STDOUT.flush
- p = wiki.find_or_new_page(page.name)
- p.content = WikiContent.new(:page => p) if p.new_record?
- p.content.text = page.text
- p.content.author = find_or_create_user(page.author) unless page.author.blank? || page.author == 'trac'
- p.content.comments = page.comment
- Time.fake(page.time) { p.new_record? ? p.save : p.content.save }
-
- next if p.content.new_record?
- migrated_wiki_edits += 1
-
- # Attachments
- page.attachments.each do |attachment|
- next unless attachment.exist?
- next if p.attachments.find_by_filename(attachment.filename.gsub(/^.*(\\|\/)/, '').gsub(/[^\w\.\-]/,'_')) #add only once per page
- attachment.open {
- a = Attachment.new :created_on => attachment.time
- a.file = attachment
- a.author = find_or_create_user(attachment.author)
- a.description = attachment.description
- a.container = p
- migrated_wiki_attachments += 1 if a.save
- }
- end
- end
-
- wiki.reload
- wiki.pages.each do |page|
- page.content.text = convert_wiki_text(page.content.text)
- Time.fake(page.content.updated_on) { page.content.save }
- end
- end
- puts
-
- puts
- puts "Components: #{migrated_components}/#{TracComponent.count}"
- puts "Milestones: #{migrated_milestones}/#{TracMilestone.count}"
- puts "Tickets: #{migrated_tickets}/#{TracTicket.count}"
- puts "Ticket files: #{migrated_ticket_attachments}/" + TracAttachment.count(:conditions => {:type => 'ticket'}).to_s
- puts "Custom values: #{migrated_custom_values}/#{TracTicketCustom.count}"
- puts "Wiki edits: #{migrated_wiki_edits}/#{wiki_edit_count}"
- puts "Wiki files: #{migrated_wiki_attachments}/" + TracAttachment.count(:conditions => {:type => 'wiki'}).to_s
- end
-
- def self.limit_for(klass, attribute)
- klass.columns_hash[attribute.to_s].limit
- end
-
- def self.encoding(charset)
- @charset = charset
- end
-
- def self.set_trac_directory(path)
- @@trac_directory = path
- raise "This directory doesn't exist!" unless File.directory?(path)
- raise "#{trac_attachments_directory} doesn't exist!" unless File.directory?(trac_attachments_directory)
- @@trac_directory
- rescue Exception => e
- puts e
- return false
- end
-
- def self.trac_directory
- @@trac_directory
- end
-
- def self.set_trac_adapter(adapter)
- return false if adapter.blank?
- raise "Unknown adapter: #{adapter}!" unless %w(sqlite3 mysql postgresql).include?(adapter)
- # If adapter is sqlite or sqlite3, make sure that trac.db exists
- raise "#{trac_db_path} doesn't exist!" if %w(sqlite3).include?(adapter) && !File.exist?(trac_db_path)
- @@trac_adapter = adapter
- rescue Exception => e
- puts e
- return false
- end
-
- def self.set_trac_db_host(host)
- return nil if host.blank?
- @@trac_db_host = host
- end
-
- def self.set_trac_db_port(port)
- return nil if port.to_i == 0
- @@trac_db_port = port.to_i
- end
-
- def self.set_trac_db_name(name)
- return nil if name.blank?
- @@trac_db_name = name
- end
-
- def self.set_trac_db_username(username)
- @@trac_db_username = username
- end
-
- def self.set_trac_db_password(password)
- @@trac_db_password = password
- end
-
- def self.set_trac_db_schema(schema)
- @@trac_db_schema = schema
- end
-
- mattr_reader :trac_directory, :trac_adapter, :trac_db_host, :trac_db_port, :trac_db_name, :trac_db_schema, :trac_db_username, :trac_db_password
-
- def self.trac_db_path; "#{trac_directory}/db/trac.db" end
- def self.trac_attachments_directory; "#{trac_directory}/attachments" end
-
- def self.target_project_identifier(identifier)
- project = Project.find_by_identifier(identifier)
- if !project
- # create the target project
- project = Project.new :name => identifier.humanize,
- :description => ''
- project.identifier = identifier
- puts "Unable to create a project with identifier '#{identifier}'!" unless project.save
- # enable issues and wiki for the created project
- project.enabled_module_names = ['issue_tracking', 'wiki']
- else
- puts
- puts "This project already exists in your Redmine database."
- print "Are you sure you want to append data to this project ? [Y/n] "
- STDOUT.flush
- exit if STDIN.gets.match(/^n$/i)
- end
- project.trackers << TRACKER_BUG unless project.trackers.include?(TRACKER_BUG)
- project.trackers << TRACKER_FEATURE unless project.trackers.include?(TRACKER_FEATURE)
- @target_project = project.new_record? ? nil : project
- @target_project.reload
- end
-
- def self.connection_params
- if trac_adapter == 'sqlite3'
- {:adapter => 'sqlite3',
- :database => trac_db_path}
- else
- {:adapter => trac_adapter,
- :database => trac_db_name,
- :host => trac_db_host,
- :port => trac_db_port,
- :username => trac_db_username,
- :password => trac_db_password,
- :schema_search_path => trac_db_schema
- }
- end
- end
-
- def self.establish_connection
- constants.each do |const|
- klass = const_get(const)
- next unless klass.respond_to? 'establish_connection'
- klass.establish_connection connection_params
- end
- end
-
- def self.encode(text)
- if RUBY_VERSION < '1.9'
- @ic ||= Iconv.new('UTF-8', @charset)
- @ic.iconv text
- else
- text.to_s.force_encoding(@charset).encode('UTF-8')
- end
- end
- end
-
- puts
- if Redmine::DefaultData::Loader.no_data?
- puts "Redmine configuration need to be loaded before importing data."
- puts "Please, run this first:"
- puts
- puts " rake redmine:load_default_data RAILS_ENV=\"#{ENV['RAILS_ENV']}\""
- exit
- end
-
- puts "WARNING: a new project will be added to Redmine during this process."
- print "Are you sure you want to continue ? [y/N] "
- STDOUT.flush
- break unless STDIN.gets.match(/^y$/i)
- puts
-
- def prompt(text, options = {}, &block)
- default = options[:default] || ''
- while true
- print "#{text} [#{default}]: "
- STDOUT.flush
- value = STDIN.gets.chomp!
- value = default if value.blank?
- break if yield value
- end
- end
-
- DEFAULT_PORTS = {'mysql' => 3306, 'postgresql' => 5432}
-
- prompt('Trac directory') {|directory| TracMigrate.set_trac_directory directory.strip}
- prompt('Trac database adapter (sqlite3, mysql2, postgresql)', :default => 'sqlite3') {|adapter| TracMigrate.set_trac_adapter adapter}
- unless %w(sqlite3).include?(TracMigrate.trac_adapter)
- prompt('Trac database host', :default => 'localhost') {|host| TracMigrate.set_trac_db_host host}
- prompt('Trac database port', :default => DEFAULT_PORTS[TracMigrate.trac_adapter]) {|port| TracMigrate.set_trac_db_port port}
- prompt('Trac database name') {|name| TracMigrate.set_trac_db_name name}
- prompt('Trac database schema', :default => 'public') {|schema| TracMigrate.set_trac_db_schema schema}
- prompt('Trac database username') {|username| TracMigrate.set_trac_db_username username}
- prompt('Trac database password') {|password| TracMigrate.set_trac_db_password password}
- end
- prompt('Trac database encoding', :default => 'UTF-8') {|encoding| TracMigrate.encoding encoding}
- prompt('Target project identifier') {|identifier| TracMigrate.target_project_identifier identifier}
- puts
-
- # Turn off email notifications
- Setting.notified_events = []
-
- TracMigrate.migrate
- end
-end
-
diff --git a/trustie2/lib/tasks/permissions.rake b/trustie2/lib/tasks/permissions.rake
deleted file mode 100644
index 02ce1b2a8..000000000
--- a/trustie2/lib/tasks/permissions.rake
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace :redmine do
- desc "List all permissions and the actions registered with them"
- task :permissions => :environment do
- puts "Permission Name - controller/action pairs"
- Redmine::AccessControl.permissions.sort {|a,b| a.name.to_s <=> b.name.to_s }.each do |permission|
- puts ":#{permission.name} - #{permission.actions.join(', ')}"
- end
- end
-end
diff --git a/trustie2/lib/tasks/redmine.rake b/trustie2/lib/tasks/redmine.rake
deleted file mode 100644
index 0ad4f2f1a..000000000
--- a/trustie2/lib/tasks/redmine.rake
+++ /dev/null
@@ -1,126 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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.
-
-namespace :redmine do
- namespace :attachments do
- desc 'Removes uploaded files left unattached after one day.'
- task :prune => :environment do
- Attachment.prune
- end
-
- desc 'Moves attachments stored at the root of the file directory (ie. created before Redmine 2.3) to their subdirectories'
- task :move_to_subdirectories => :environment do
- Attachment.move_from_root_to_target_directory
- end
- end
-
- namespace :tokens do
- desc 'Removes expired tokens.'
- task :prune => :environment do
- Token.destroy_expired
- end
- end
-
- namespace :watchers do
- desc 'Removes watchers from what they can no longer view.'
- task :prune => :environment do
- Watcher.prune
- end
- end
-
- desc 'Fetch changesets from the repositories'
- task :fetch_changesets => :environment do
- Repository.fetch_changesets
- end
-
- desc 'Migrates and copies plugins assets.'
- task :plugins do
- Rake::Task["redmine:plugins:migrate"].invoke
- Rake::Task["redmine:plugins:assets"].invoke
- end
-
- namespace :plugins do
- desc 'Migrates installed plugins.'
- task :migrate => :environment do
- name = ENV['NAME']
- version = nil
- version_string = ENV['VERSION']
- if version_string
- if version_string =~ /^\d+$/
- version = version_string.to_i
- if name.nil?
- abort "The VERSION argument requires a plugin NAME."
- end
- else
- abort "Invalid VERSION #{version_string} given."
- end
- end
-
- begin
- Redmine::Plugin.migrate(name, version)
- rescue Redmine::PluginNotFound
- abort "Plugin #{name} was not found."
- end
-
- Rake::Task["db:schema:dump"].invoke
- end
-
- desc 'Copies plugins assets into the public directory.'
- task :assets => :environment do
- name = ENV['NAME']
-
- begin
- Redmine::Plugin.mirror_assets(name)
- rescue Redmine::PluginNotFound
- abort "Plugin #{name} was not found."
- end
- end
-
- desc 'Runs the plugins tests.'
- task :test do
- Rake::Task["redmine:plugins:test:units"].invoke
- Rake::Task["redmine:plugins:test:functionals"].invoke
- Rake::Task["redmine:plugins:test:integration"].invoke
- end
-
- namespace :test do
- desc 'Runs the plugins unit tests.'
- Rake::TestTask.new :units => "db:test:prepare" do |t|
- t.libs << "test"
- t.verbose = true
- t.pattern = "plugins/#{ENV['NAME'] || '*'}/test/unit/**/*_test.rb"
- end
-
- desc 'Runs the plugins functional tests.'
- Rake::TestTask.new :functionals => "db:test:prepare" do |t|
- t.libs << "test"
- t.verbose = true
- t.pattern = "plugins/#{ENV['NAME'] || '*'}/test/functional/**/*_test.rb"
- end
-
- desc 'Runs the plugins integration tests.'
- Rake::TestTask.new :integration => "db:test:prepare" do |t|
- t.libs << "test"
- t.verbose = true
- t.pattern = "plugins/#{ENV['NAME'] || '*'}/test/integration/**/*_test.rb"
- end
- end
- end
-end
-
-# Load plugins' rake tasks
-Dir[File.join(Rails.root, "plugins/*/lib/tasks/**/*.rake")].sort.each { |ext| load ext }
diff --git a/trustie2/lib/tasks/reminder.rake b/trustie2/lib/tasks/reminder.rake
deleted file mode 100644
index 67661a361..000000000
--- a/trustie2/lib/tasks/reminder.rake
+++ /dev/null
@@ -1,43 +0,0 @@
-# Redmine - project management software
-# Copyright (C) 2006-2013 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.
-
-desc <<-END_DESC
-Send reminders about issues due in the next days.
-
-Available options:
- * days => number of days to remind about (defaults to 7)
- * tracker => id of tracker (defaults to all trackers)
- * project => id or identifier of project (defaults to all projects)
- * users => comma separated list of user/group ids who should be reminded
-
-Example:
- rake redmine:send_reminders days=7 users="1,23, 56" RAILS_ENV="production"
-END_DESC
-
-namespace :redmine do
- task :send_reminders => :environment do
- options = {}
- options[:days] = ENV['days'].to_i if ENV['days']
- options[:project] = ENV['project'] if ENV['project']
- options[:tracker] = ENV['tracker'].to_i if ENV['tracker']
- options[:users] = (ENV['users'] || '').split(',').each(&:strip!)
-
- Mailer.with_synched_deliveries do
- Mailer.reminders(options)
- end
- end
-end
diff --git a/trustie2/lib/tasks/rubyzip.rake b/trustie2/lib/tasks/rubyzip.rake
deleted file mode 100644
index 349ced29b..000000000
--- a/trustie2/lib/tasks/rubyzip.rake
+++ /dev/null
@@ -1,38 +0,0 @@
-desc "nyan ruby zip operation"
-task :zip do
- puts "input rake zip:clean_tmp will removed tmp/*.zip ."
-end
-
-namespace :zip do
- desc "ruby zip sweeper"
- task :clean_tmp do
- unless File.exist?(Dir.pwd+"/tmp/archiveZip")
- puts "tmp/archiveZip folder is not exist. "
- next
- end
-
- puts "ruby zip sweeping..."
- Dir.chdir('tmp/archiveZip') do
- Dir['*'].select do |file|
- if file =~ /archive_\d+\.zip/
- File.delete(file)
- puts "#{file} is deleted."
- end
- end
- end
- puts "ruby zip sweeping is done."
- end
-end
-
-desc "create tmp file, to test"
-file 'tmp/test.yml' do
- require 'yaml'
- var = {
- :name => "name",
- :age => "age",
- :agent => "agent"
- }
- File.open('tmp/test.yml', 'w') do |f|
- f.write YAML.dump({'conf' => var })
- end
-end
\ No newline at end of file
diff --git a/trustie2/lib/tasks/solr_incremental_index.rake b/trustie2/lib/tasks/solr_incremental_index.rake
deleted file mode 100644
index ba963352b..000000000
--- a/trustie2/lib/tasks/solr_incremental_index.rake
+++ /dev/null
@@ -1,64 +0,0 @@
-namespace :solr_incremental_index do
- task :index => :environment do
- batch_size = 1000
- unless SolrIncrementalIndexCursor.where(name: 'OpenSourceProject').exists?
- osp_new_cursor=SolrIncrementalIndexCursor.new(name: 'OpenSourceProject', cursor: 0)
- osp_new_cursor.save
- end
- unless SolrIncrementalIndexCursor.where(name: 'RelativeMemo').exists?
- rm_new_cursor=SolrIncrementalIndexCursor.new(name: 'RelativeMemo', cursor: 0)
- rm_new_cursor.save
- end
-
- cur_id=[]
- osp_cursor=SolrIncrementalIndexCursor.where(name: 'OpenSourceProject').last
- relative_memo_cursor=SolrIncrementalIndexCursor.where(name: 'RelativeMemo').last
- cur_id[0]=osp_cursor.cursor
- cur_id[1]=relative_memo_cursor.cursor
- puts("OpenSourceProjectCursor: "+cur_id[0].to_s)
- puts("RelativeMemo: "+cur_id[1].to_s)
-
- while true
- begin
- osp_max_id = OpenSourceProject.maximum(:id)
- rm_max_id = RelativeMemo.maximum(:id)
- #Thread.new do
- while osp_max_id>cur_id[0] || rm_max_id>cur_id[1] do
- begin
- if osp_max_id > cur_id[0]
- OpenSourceProject.where("id > #{cur_id[0]} AND id < #{cur_id[0]+batch_size}").each do |osp_info|
- #puts('start')
- Sunspot.index(osp_info)
- cur_id[0]=osp_info.id
- puts("OpenSourceProject: "+cur_id[0].to_s)
- #puts('inside')
- end
- end
- osp_cursor.update_attribute('cursor', cur_id[0])
-
- if rm_max_id > cur_id[1]
- RelativeMemo.where("id > #{cur_id[1]} AND id < #{cur_id[1]+batch_size}").limit(1000).each do |memo|
- Sunspot.index(memo)
- cur_id[1]=memo.id
- puts("RelativeMemo: "+cur_id[1].to_s)
- end
- end
- relative_memo_cursor.update_attribute('cursor', cur_id[1])
- #puts("while")
- #sleep(600)
- #puts('after sleep')
- rescue Exception => e
- puts e
- end
- end
-
- rescue Exception => e
- puts e
- end
-
- sleep(60)
-
- # end
- end
- end
-end
diff --git a/trustie2/lib/tasks/sync_osp_relative_memos_num.rake b/trustie2/lib/tasks/sync_osp_relative_memos_num.rake
deleted file mode 100644
index bc547ef22..000000000
--- a/trustie2/lib/tasks/sync_osp_relative_memos_num.rake
+++ /dev/null
@@ -1,49 +0,0 @@
-namespace :sync_osp_relative_memos_num do
- task :start => :environment do
- while true
- batch_size = 1000
- unless SolrIncrementalIndexCursor.where(name: 'OpenSourceProjectForSyncNum').exists?
- rm2osp_new_cursor=SolrIncrementalIndexCursor.new(name: 'OpenSourceProjectForSyncNum', cursor: 0)
- rm2osp_new_cursor.save
- end
-
- cur_id = 0
- rm2osp_cursor=SolrIncrementalIndexCursor.where(name: 'OpenSourceProjectForSyncNum').last
- cur_id = rm2osp_cursor.cursor
- puts(cur_id)
-
-
- begin
- max_id = OpenSourceProject.maximum(:id)
- puts("max: "+max_id.to_s)
- #Thread.new do
- while cur_id < max_id do
- begin
- OpenSourceProject.where("id > #{cur_id} AND id < #{cur_id+batch_size}").each do |osp|
- #puts('start')
- RelativeMemoToOpenSourceProject.set_table_name RelativeMemoToOpenSourceProject.getTableName osp.id
- table_name = RelativeMemoToOpenSourceProject.getTableName osp.id
- sql = "select id AS num FROM " + table_name + " where osp_id = ?"
- num = (RelativeMemoToOpenSourceProject.find_by_sql [sql, osp.id]).count
- osp.update_attribute('relative_memos_num', num)
- cur_id=osp.id
- puts("OpenSourceProject: "+cur_id.to_s)
- #puts('inside')
- end
- rm2osp_cursor.update_attribute('cursor', cur_id)
-
- rescue Exception => e
- puts e
- end
- end
-
- rescue Exception => e
- puts e
- end
-
- sleep(60)
-
- # end
- end
- end
-end
diff --git a/trustie2/lib/tasks/sync_osp_status.rake b/trustie2/lib/tasks/sync_osp_status.rake
deleted file mode 100644
index aad561f6e..000000000
--- a/trustie2/lib/tasks/sync_osp_status.rake
+++ /dev/null
@@ -1,144 +0,0 @@
-namespace :sync_osp_status do
- desc 'sync osp composite_score & view_num'
- task :start => :environment do
-
- #if File.exist?(pid_path)
- # existing_pid = IO.read(pid_path).to_i
- # begin
- # Process.kill(0, existing_pid)
- # raise(AlreadyRunningError, "Server is already running with PID #{existing_pid}")
- # rescue Errno::ESRCH
- # STDERR.puts("Removing stale PID file at #{pid_path}")
- # FileUtils.rm(pid_path)
- # end
- #end
-
-
- # run
- # sync_composite_score
- sync_popularity_and_composite_score
- #Process.fork do
- # pid = fork do
- # Process.setsid
- # STDIN.reopen('/dev/null')
- # STDOUT.reopen('/dev/null')
- # STDERR.reopen(STDOUT)
- # run
- # end
- # FileUtils.mkdir_p(pid_dir)
- # File.open(pid_path, 'w') do |file|
- # file << pid
- # end
- #end
-
- end
-
- def sync_popularity_and_composite_score
- batch_size = 1000
- sleep_time = 86400
-
- while true
- cur_id = 0
- begin
- max_id = OpenSourceProject.maximum(:id)
- puts("max: "+max_id.to_s)
- while cur_id < max_id do
- begin
- OpenSourceProject.where("id > #{cur_id} AND id < #{cur_id+batch_size}").each do |osp|
-
- # rs=[osp_id, view_num, count]
- rs = RelativeMemoToOpenSourceProject.set_table_name(RelativeMemoToOpenSourceProject.getTableName(osp.id)).where(osp_id: osp.id).select("osp_id, SUM(view_num) AS total, COUNT(*) AS num")
- unless rs.first.nil?
- osp.update_attribute(:view_num, rs.first.total)
- # osp.update_attribute(:composite_score, rs.first.num)
- osp.update_attribute(:relative_memos_num, rs.first.num)
- end
- popularities = RelativeMemoToOpenSourceProject.set_table_name(RelativeMemoToOpenSourceProject.getTableName(osp.id)).where(osp_id: osp.id).group("YEAR(created_time),MONTH(created_time)").select("osp_id, YEAR(created_time) AS year, MONTH(created_time) AS month, COUNT(*) AS num")
- popularities.each do |popularity|
- unless popularity.year.nil?||popularity.month.nil?
- year = popularity.year
- month = popularity.month
- num =popularity.num
- if !OpenSourceProjectPopularity.where(osp_id: osp.id, year_col: year, month_col: month).exists?
- OpenSourceProjectPopularity.create!(osp_id: osp.id, year_col: year, month_col: month, popularity: num)
- else
- OpenSourceProjectPopularity.where(osp_id: osp.id, year_col: year, month_col: month).first.update_attribute(:popularity, num)
- end
- end
- end
- cur_id=osp.id
- puts("OpenSourceProject: "+cur_id.to_s)
- end
- rescue Exception => e
- puts e
- end
- end
-
- rescue Exception => e
- puts e
- end
-
- puts 'sleep for '+sleep_time.to_s+' ms!!!'
- sleep(86400)
-
- #end
- end
- end
-
- def sync_composite_score
- rm_osp_count = Hash.new
- osp_id_set = Set.new
-
- range = 1..70
- base_table='relative_memo_to_open_source_projects_'
- range.each do |i|
-
- ####计算一段时间内的帖子新匹配多少项目以及查询项目集合
- table = base_table+i.to_s
- rm_records = RelativeMemoToOpenSourceProject.set_table_name(table).group(:relative_memo_id).select([:relative_memo_id, 'COUNT(*) AS num'])
- osp_records = RelativeMemoToOpenSourceProject.set_table_name(table).group(:osp_id).select(:osp_id)
- rm_records.each do |record|
- ######## rm_osp_count_local中没有则添加,有则更新
- rm_osp_count[record.relative_memo_id] = ((rm_osp_count.key? record.relative_memo_id) ? (rm_osp_count[record.relative_memo_id]+record.num) : record.num)
- end
-
- osp_records.each do |record|
- osp_id_set.add record.osp_id
- end
-
- puts i
- end
-
- osp_id_set.each do |osp_id|
- osp = OpenSourceProject.find(osp_id)
- composite_score =calc_composite_score(rm_osp_count, osp_id_set, osp)
- puts composite_score
- osp.update_attribute(:composite_score, composite_score)
- end
- end
-
- def calc_composite_score hash, set, osp
- score = 0
- rm_ids=RelativeMemoToOpenSourceProject.set_table_name(RelativeMemoToOpenSourceProject.getTableName(osp.id)).where(osp_id: osp.id).select(:relative_memo_id)
- rm_ids.each do |id|
- #puts id.relative_memo_id
- #puts 1/hash[id.relative_memo_id].to_f
- #puts hash.key? id.relative_memo_id
- score+=((hash.key? id.relative_memo_id) ? 1/hash[id.relative_memo_id].to_f : 0)
- #puts score
- end
- score
- end
-
- def pid_path
- File.join(pid_dir, pid_file)
- end
-
- def pid_file
- @pid_file || 'sync_osp_status.pid'
- end
-
- def pid_dir
- File.expand_path(@pid_dir || FileUtils.pwd)
- end
-end
diff --git a/trustie2/lib/tasks/testing.rake b/trustie2/lib/tasks/testing.rake
deleted file mode 100644
index cfb8e77f9..000000000
--- a/trustie2/lib/tasks/testing.rake
+++ /dev/null
@@ -1,110 +0,0 @@
-### From http://svn.geekdaily.org/public/rails/plugins/generally_useful/tasks/coverage_via_rcov.rake
-
-namespace :test do
- desc 'Measures test coverage'
- task :coverage do
- rm_f "coverage"
- rm_f "coverage.data"
- rcov = "rcov --rails --aggregate coverage.data --text-summary -Ilib --html --exclude gems/"
- files = %w(unit functional integration).map {|dir| Dir.glob("test/#{dir}/**/*_test.rb")}.flatten.join(" ")
- system("#{rcov} #{files}")
- end
-
- desc 'Run unit and functional scm tests'
- task :scm do
- errors = %w(test:scm:units test:scm:functionals).collect do |task|
- begin
- Rake::Task[task].invoke
- nil
- rescue => e
- task
- end
- end.compact
- abort "Errors running #{errors.to_sentence(:locale => :en)}!" if errors.any?
- end
-
- namespace :scm do
- namespace :setup do
- desc "Creates directory for test repositories"
- task :create_dir do
- FileUtils.mkdir_p Rails.root + '/tmp/test'
- end
-
- supported_scms = [:subversion, :cvs, :bazaar, :mercurial, :git, :darcs, :filesystem]
-
- desc "Creates a test subversion repository"
- task :subversion => :create_dir do
- repo_path = "tmp/test/subversion_repository"
- unless File.exists?(repo_path)
- system "svnadmin create #{repo_path}"
- system "gunzip < test/fixtures/repositories/subversion_repository.dump.gz | svnadmin load #{repo_path}"
- end
- end
-
- desc "Creates a test mercurial repository"
- task :mercurial => :create_dir do
- repo_path = "tmp/test/mercurial_repository"
- unless File.exists?(repo_path)
- bundle_path = "test/fixtures/repositories/mercurial_repository.hg"
- system "hg init #{repo_path}"
- system "hg -R #{repo_path} pull #{bundle_path}"
- end
- end
-
- (supported_scms - [:subversion, :mercurial]).each do |scm|
- desc "Creates a test #{scm} repository"
- task scm => :create_dir do
- unless File.exists?("tmp/test/#{scm}_repository")
- # system "gunzip < test/fixtures/repositories/#{scm}_repository.tar.gz | tar -xv -C tmp/test"
- system "tar -xvz -C tmp/test -f test/fixtures/repositories/#{scm}_repository.tar.gz"
- end
- end
- end
-
- desc "Creates all test repositories"
- task :all => supported_scms
- end
-
- desc "Updates installed test repositories"
- task :update do
- require 'fileutils'
- Dir.glob("tmp/test/*_repository").each do |dir|
- next unless File.basename(dir) =~ %r{^(.+)_repository$} && File.directory?(dir)
- scm = $1
- next unless fixture = Dir.glob("test/fixtures/repositories/#{scm}_repository.*").first
- next if File.stat(dir).ctime > File.stat(fixture).mtime
-
- FileUtils.rm_rf dir
- Rake::Task["test:scm:setup:#{scm}"].execute
- end
- end
-
- Rake::TestTask.new(:units => "db:test:prepare") do |t|
- t.libs << "test"
- t.verbose = true
- t.test_files = FileList['test/unit/repository*_test.rb'] + FileList['test/unit/lib/redmine/scm/**/*_test.rb']
- end
- Rake::Task['test:scm:units'].comment = "Run the scm unit tests"
-
- Rake::TestTask.new(:functionals => "db:test:prepare") do |t|
- t.libs << "test"
- t.verbose = true
- t.test_files = FileList['test/functional/repositories*_test.rb']
- end
- Rake::Task['test:scm:functionals'].comment = "Run the scm functional tests"
- end
-
- Rake::TestTask.new(:rdm_routing) do |t|
- t.libs << "test"
- t.verbose = true
- t.test_files = FileList['test/integration/routing/*_test.rb']
- end
- Rake::Task['test:rdm_routing'].comment = "Run the routing tests"
-
- Rake::TestTask.new(:ui => "db:test:prepare") do |t|
- t.libs << "test"
- t.verbose = true
- t.test_files = FileList['test/ui/**/*_test.rb']
- end
- Rake::Task['test:ui'].comment = "Run the UI tests with Capybara (PhantomJS listening on port 4444 is required)"
-end
diff --git a/trustie2/lib/tasks/yardoc.rake b/trustie2/lib/tasks/yardoc.rake
deleted file mode 100644
index aa6c5eeb0..000000000
--- a/trustie2/lib/tasks/yardoc.rake
+++ /dev/null
@@ -1,21 +0,0 @@
-begin
- require 'yard'
-
- YARD::Rake::YardocTask.new do |t|
- files = ['lib/**/*.rb', 'app/**/*.rb']
- files << Dir['vendor/plugins/**/*.rb'].reject {|f| f.match(/test/) } # Exclude test files
- t.files = files
-
- static_files = ['doc/CHANGELOG',
- 'doc/COPYING',
- 'doc/INSTALL',
- 'doc/RUNNING_TESTS',
- 'doc/UPGRADING'].join(',')
-
- t.options += ['--output-dir', './doc/app', '--files', static_files]
- end
-
-rescue LoadError
- # yard not installed (gem install yard)
- # http://yardoc.org
-end
diff --git a/trustie2/public/404.html b/trustie2/public/404.html
deleted file mode 100644
index 8f2a53fe2..000000000
--- a/trustie2/public/404.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-Trustie 404 error
-
-
- Page not found
- The page you were trying to access doesn't exist or has been removed.
-
-
-
diff --git a/trustie2/public/500.html b/trustie2/public/500.html
deleted file mode 100644
index 6b6aad46d..000000000
--- a/trustie2/public/500.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
- Trustie 500 error
-
-
-
-
-
-
-
-
-
-
diff --git a/trustie2/public/application.css b/trustie2/public/application.css
deleted file mode 100644
index 4003adcee..000000000
--- a/trustie2/public/application.css
+++ /dev/null
@@ -1,1148 +0,0 @@
-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;padding: 2px 10px 1px 0px;margin: 0 0 10px 0;}
-#content h1, h2, h3, h4 {color: #555;}
-h2, .wiki h1 {font-size: 20px;}
-h3, .wiki h2 {font-size: 16px;}
-h4, .wiki h3 {font-size: 13px;}
-h4 {border-bottom: 1px dotted #bbb;}
-
-/***** Layout *****/
-#wrapper {background: white;}
-
-#top-menu {background: #3E5B76; color: #000; height:1.8em; font-size: 1.0em; 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: #000000; margin-right: 8px; font-weight: bold;}
-#top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; }
-
-#account {float:right;}
-
-#header {min-height:5.3em;margin:0;background-color:#628DB6;color:#f8f8f8; padding: 4px 8px 20px 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: #039ea0;
- 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 6px 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; }
-
-div.modal { border-radius:5px; background:#fff; z-index:50; padding:4px;}
-div.modal h3.title {display:none;}
-div.modal p.buttons {text-align:right; margin-bottom:0;}
-
-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: #169; 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; }
-a.project.closed, a.project.closed:link, a.project.closed:visited { color: #999; }
-a.user.locked, a.user.locked:link, a.user.locked:visited {color: #999;}
-
-#sidebar a.selected {line-height:1.7em; padding:1px 3px 2px 2px; margin-left:-2px; background-color:#9DB9D5; color:#fff; border-radius:2px;}
-#sidebar a.selected:hover {text-decoration:none;}
-#admin-menu a {line-height:1.7em;}
-#admin-menu a.selected {padding-left: 20px !important; background-position: 2px 40%;}
-
-a.collapsible {padding-left: 12px; background: url(../images/arrow_expanded.png) no-repeat -3px 40%;}
-a.collapsible.collapsed {background: url(../images/arrow_collapsed.png) no-repeat -5px 40%;}
-
-a#toggle-completed-versions {color:#999;}
-/***** 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; padding-right:10px; }
-table.list td.id { width: 2%; text-align: center;}
-table.list td.checkbox { width: 15px; padding: 2px 0 0 0; }
-table.list td.checkbox input {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.closed, tr.project.archived { color: #aaa; }
-tr.project.closed a, tr.project.archived a { color: #aaa; }
-
-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.title, tr.issue td.category, td.assigned_to, tr.issue td.string, tr.issue td.text, tr.issue td.relations { white-space: normal; }
-tr.issue td.title, tr.issue td.relations { text-align: left; }
-tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;}
-tr.issue td.relations span {white-space: nowrap;}
-table.issues td.description {color:#777; font-size:90%; padding:4px 4px 4px 24px; text-align:left; white-space:normal;}
-table.issues td.description pre {white-space:normal;}
-
-tr.issue.idnt td.title a {background: url(../images/bullet_arrow_right.png) no-repeat 0 50%; padding-left: 16px;}
-tr.issue.idnt-1 td.title {padding-left: 0.5em;}
-tr.issue.idnt-2 td.title {padding-left: 2em;}
-tr.issue.idnt-3 td.title {padding-left: 3.5em;}
-tr.issue.idnt-4 td.title {padding-left: 5em;}
-tr.issue.idnt-5 td.title {padding-left: 6.5em;}
-tr.issue.idnt-6 td.title {padding-left: 8em;}
-tr.issue.idnt-7 td.title {padding-left: 9.5em;}
-tr.issue.idnt-8 td.title {padding-left: 11em;}
-tr.issue.idnt-9 td.title {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.filename_no_report { width: 70%; }
-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.entry.file td.filename_no_report 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 { height: 20px }
-tr.changeset ul, ol { margin-top: 0px; margin-bottom: 0px; }
-tr.changeset td.revision_graph { width: 15%; background-color: #fffffb; }
-tr.changeset td.author { text-align: center; width: 15%; white-space:nowrap;}
-tr.changeset td.committed_on { text-align: center; width: 15%; white-space:nowrap;}
-
-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.title { 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.title { background: url(../images/locked.png) no-repeat 0 1px; }
-tr.message.sticky td.title { 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; white-space:nowrap; }
-
-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; }
-
-table.permissions td.role {color:#999;font-size:90%;font-weight:normal !important;text-align:center;vertical-align:bottom;}
-
-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.issue, 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 {position:relative; top:-1px; color:#fff; font-size:10px; background:#9DB9D5; padding:0px 6px 1px 6px; border-radius:3px; margin-left:4px;}
-tr.group a.toggle-all { color: #aaa; font-size: 80%; font-weight: normal; display:none;}
-tr.group:hover a.toggle-all { display:inline;}
-a.toggle-all:hover {text-decoration:none;}
-
-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; }
-table.boards td.topic-count, table.boards td.message-count {text-align:center;}
-table.boards td.last-message {font-size:80%;}
-
-table.messages td.author, table.messages td.created_on, table.messages td.reply-count {text-align:center;}
-
-table.query-columns {
- border-collapse: collapse;
- border: 0;
-}
-
-table.query-columns td.buttons {
- vertical-align: middle;
- text-align: center;
-}
-
-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; vertical-align: middle;}
-#watchers a.delete:hover {opacity: 1;}
-#watchers img.gravatar {margin: 0 4px 2px 0;}
-
-span#watchers_inputs {overflow:auto; display:block;}
-span.search_for_watchers {display:block;}
-span.search_for_watchers, span.add_attachment {font-size:80%; line-height:2.5em;}
-span.search_for_watchers a, span.add_attachment a {padding-left:16px; background: url(../images/bullet_add.png) no-repeat 0 50%; }
-
-
-.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; }
-
-.splitcontent {overflow:auto;}
-.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%; resize:vertical;}
-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.title div div { padding-left: 16px; }
-div.issue div.title p {margin: 0; margin-bottom: 0.1em; font-size: 90%; color: #999;}
-div.issue div.title>div>p { margin-top: 0.5em; }
-div.issue div.title h3 {margin: 0; margin-bottom: 0.1em;}
-div.issue span.private { position:relative; bottom: 2px; text-transform: uppercase; background: #d22; color: #fff; font-weight:bold; padding: 0px 2px 0px 2px; font-size: 60%; margin-right: 2px; border-radius: 2px;}
-div.issue .next-prev-links {color:#999;}
-div.issue table.attributes th {width:22%;}
-div.issue table.attributes td {width:28%;}
-
-#issue_tree table.issues, #relations table.issues { border: 0; }
-#issue_tree td.checkbox, #relations td.checkbox {display:none;}
-#relations td.buttons {padding:0;}
-
-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: 2.1em; }
-fieldset#filters td.field { width:230px; }
-fieldset#filters td.operator { width:180px; }
-fieldset#filters td.operator select {max-width:170px;}
-fieldset#filters td.values { white-space:nowrap; }
-fieldset#filters td.values select {min-width:130px;}
-fieldset#filters td.values input {height:1em;}
-fieldset#filters td.add-filter { text-align: right; vertical-align: top; }
-
-.toggle-multiselect {background: url(../images/bullet_toggle_plus.png) no-repeat 0% 40%; padding-left:8px; margin-left:0; cursor:pointer;}
-.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;}
-
-.journal ul.details img {margin:0 0 -3px 4px;}
-div.journal {overflow:auto;}
-div.journal.private-notes {border-left:2px solid #d22; padding-left:4px; margin-left:-6px;}
-
-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; }
-div#activity dt.grouped {margin-left:5em;}
-div#activity dd.grouped {margin-left:9em;}
-
-#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%; }
-body.controller-versions.action-show div#roadmap .related-issues {width:70%;}
-
-div#version-summary { float:right; width:28%; margin-left: 16px; margin-bottom: 16px; background-color: #fff; }
-div#version-summary fieldset { margin-bottom: 1em; }
-div#version-summary fieldset.time-tracking table { width:100%; }
-div#version-summary th, div#version-summary td.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.subtotal { font-style: italic; color:#777;}
-table#time-report tbody tr.subtotal td.hours { color:#b0b0b0; }
-table#time-report tbody tr.total { font-weight: bold; background-color:#EEEEEE; border-top:1px solid #e4e4e4;}
-table#time-report .hours-dec { font-size: 0.9em; }
-
-div.wiki-page .contextual a {opacity: 0.4}
-div.wiki-page .contextual a:hover {opacity: 1}
-
-form .attributes select { width: 60%; }
-input#issue_title { width: 99%; }
-select#issue_done_ratio { width: 95px; }
-
-ul.projects {margin:0; padding-left:1em;}
-ul.projects ul {padding-left:1.6em;}
-ul.projects.root {margin:0; padding:0;}
-ul.projects li {list-style-type:none;}
-
-#projects-index ul.projects ul.projects { border-left: 3px solid #e0e0e0; padding-left:1em;}
-#projects-index ul.projects li.root {margin-bottom: 1em;}
-#projects-index ul.projects li.child {margin-top: 1em;}
-#projects-index 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%; }
-
-#notified-projects ul, #tracker_project_ids ul {max-height:250px; overflow-y:auto;}
-
-#related-issues li img {vertical-align:middle;}
-
-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_login, #user_firstname, #user_lastname, #user_mail, #my_account_form select, #user_form select, #user_identity_url { width: 90%; }
-
-#workflow_copy_form select { width: 200px; }
-table.transitions td.enabled {background: #bfb;}
-table.fields_permissions select {font-size:90%}
-table.fields_permissions td.readonly {background:#ddd;}
-table.fields_permissions td.required {background:#d88;}
-
-textarea#custom_field_possible_values {width: 99%}
-textarea#custom_field_default_value {width: 99%}
-
-input#content_comments {width: 99%}
-
-p.pagination {margin-top:8px; font-size: 90%}
-
-/***** Tabular forms ******/
-.tabular p{
- margin: 0;
- padding: 3px 0 3px 0;
- padding-left: 180px; /* width of left column containing the label elements */
- min-height: 1.8em;
- clear:left;
-}
-
-html>body .tabular p {overflow:hidden;}
-
-.tabular label{
- font-weight: bold;
- float: left;
- text-align: right;
- /* width of left column */
- margin-left: -180px;
- /* width of labels. Should be smaller than left column to create some right margin */
- width: 175px;
-}
-
-.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{
- font-weight: normal;
- float:none;
- margin-left: 5px !important;
- width: auto;
-}
-
-label.no-css {
- font-weight: inherit;
- float:none;
- text-align:left;
- margin-left:0px;
- 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%; }
-
-.settings.enabled_scm table {width:100%}
-.settings.enabled_scm td.scm_name{ font-weight: bold; }
-
-fieldset.settings label { display: block; }
-fieldset#notified_events .parent { padding-left: 20px; }
-
-span.required {color: #bb0000;}
-.summary {font-style: italic;}
-
-#attachments_fields input.description {margin-left:4px; width:340px;}
-#attachments_fields span {display:block; white-space:nowrap;}
-#attachments_fields input.filename {border:0; height:1.8em; width:250px; color:#555; background-color:inherit; background:url(../images/attachment.png) no-repeat 1px 50%; padding-left:18px;}
-#attachments_fields .ajax-waiting input.filename {background:url(../images/hourglass.png) no-repeat 0px 50%;}
-#attachments_fields .ajax-loading input.filename {background:url(../images/loading.gif) no-repeat 0px 50%;}
-#attachments_fields div.ui-progressbar { width: 100px; height:14px; margin: 2px 0 -5px 8px; display: inline-block; }
-a.remove-upload {background: url(../images/delete.png) no-repeat 1px 50%; width:1px; display:inline-block; padding-left:16px;}
-a.remove-upload:hover {text-decoration:none !important;}
-
-div.fileover { background-color: lavender; }
-
-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; }
-
-div.thumbnails {margin-top:0.6em;}
-div.thumbnails div {background:#fff;border:2px solid #ddd;display:inline-block;margin-right:2px;}
-div.thumbnails img {margin: 3px;}
-
-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; }
-
-em.info {font-style:normal;font-size:90%;color:#888;display:block;}
-em.info.error {padding-left:20px; background:url(../images/exclamation.png) no-repeat 0 50%;}
-
-textarea.text_cf {width:90%;}
-
-#tab-content-modules fieldset p {margin:3px 0 4px 0;}
-
-#tab-content-members .splitcontentleft, #tab-content-memberships .splitcontentleft, #tab-content-users .splitcontentleft {width: 64%;}
-#tab-content-members .splitcontentright, #tab-content-memberships .splitcontentright, #tab-content-users .splitcontentright {width: 34%;}
-#tab-content-members fieldset, #tab-content-memberships fieldset, #tab-content-users fieldset {padding:1em; margin-bottom: 1em;}
-#tab-content-members fieldset legend, #tab-content-memberships fieldset legend, #tab-content-users fieldset legend {font-weight: bold;}
-#tab-content-members fieldset label, #tab-content-memberships fieldset label, #tab-content-users fieldset label {display: block;}
-#tab-content-members #principals, #tab-content-users #principals {max-height: 400px; overflow: auto;}
-
-#users_for_watcher {height: 200px; overflow:auto;}
-#users_for_watcher label {display: block;}
-
-table.members td.group { padding-left: 20px; background: url(../images/group.png) no-repeat 0% 50%; }
-
-input#principal_search, input#user_search {width:90%}
-
-input.autocomplete {
- background: #fff url(../images/magnifier.png) no-repeat 2px 50%; padding-left:20px;
- border:1px solid #9EB1C2; border-radius:2px; height:1.5em;
-}
-input.autocomplete.ajax-loading {
- background-image: url(../images/loading.gif);
-}
-
-/***** Flash & error messages ****/
-#errorExplanation, div.flash, .nodata, .warning, .conflict {
- 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, .conflict {
- 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; }
-
-.conflict-details {font-size:80%;}
-
-/***** 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;
-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;
-}
-
-img.ui-datepicker-trigger {
- cursor: pointer;
- vertical-align: middle;
- margin-left: 4px;
-}
-
-/***** Progress bar *****/
-table.progress {
- border-collapse: collapse;
- border-spacing: 0pt;
- empty-cells: show;
- text-align: center;
- float:left;
- margin: 1px 6px 1px 0px;
-}
-
-table.progress td { height: 1em; }
-table.progress td.closed { background: #BAE0BA none repeat scroll 0%; }
-table.progress td.done { background: #D3EDD3 none repeat scroll 0%; }
-table.progress td.todo { background: #eee none repeat scroll 0%; }
-p.percent {font-size: 80%;}
-p.progress-info {clear: left; font-size: 80%; margin-top:-4px; color:#777;}
-
-#roadmap table.progress td { height: 1.2em; }
-/***** 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:0.5em; width: 2000px; border-bottom: 1px solid #bbbbbb;}
-#content .tabs ul li {
- float:left;
- list-style-type:none;
- white-space:nowrap;
- margin-right:4px;
- 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: #f6f6f6;
- color:#999;
- font-weight:bold;
- border-top-left-radius:3px;
- border-top-right-radius:3px;
-}
-
-#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;
- color:#444;
-}
-
-#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%;
- border-top-left-radius:3px;
-}
-
-button.tab-right {
- right: 0;
- background: #eeeeee url(../images/bullet_arrow_right.png) no-repeat 50% 50%;
- border-top-right-radius:3px;
-}
-
-/***** Diff *****/
-.diff_out { background: #fcc; }
-.diff_out span { background: #faa; }
-.diff_in { background: #cfc; }
-.diff_in span { background: #afa; }
-
-.text-diff {
- padding: 1em;
- background-color:#f6f6f6;
- color:#505050;
- border: 1px solid #e4e4e4;
-}
-
-/***** Wiki *****/
-div.wiki table {
- border-collapse: collapse;
- margin-bottom: 1em;
-}
-
-div.wiki table, div.wiki td, div.wiki th {
- border: 1px solid #bbb;
- padding: 4px;
-}
-
-div.wiki .noborder, div.wiki .noborder td, div.wiki .noborder th {border:0;}
-
-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 ul, div.wiki ol {margin-bottom:1em;}
-
-div.wiki pre {
- margin: 1em 1em 1em 1.6em;
- padding: 8px;
- background-color: #fafafa;
- border: 1px solid #e2e2e2;
- 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; font-size:12px;}
-div.wiki ul.toc li li {margin-left: 1.5em; font-size:10px;}
-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_hdr.nwday {background-color:#f1f1f1;}
-
-.gantt_titles { font-size: 0.8em; }
-.gantt_titles div { line-height:16px;height:16px;overflow:hidden;white-space:nowrap;text-overflow: ellipsis; }
-
-.task {
- position: absolute;
- height:8px;
- font-size:0.8em;
- color:#888;
- padding:0;
- margin:0;
- line-height:16px;
- 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-passwd { background-image: url(../images/textfield_key.png); }
-.icon-test { background-image: url(../images/bullet_go.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-java { background-image: url(../images/files/java.png); }
-.icon-file.text-x-javascript { background-image: url(../images/files/js.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.text-css { background-image: url(../images/files/css.png); }
-.icon-file.text-html { background-image: url(../images/files/html.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;
- vertical-align: middle;
-}
-
-div.issue img.gravatar {
- float: left;
- margin: 0 6px 0 0;
- padding: 5px;
-}
-
-div.issue table img.gravatar {
- height: 14px;
- width: 14px;
- padding: 2px;
- float: left;
- margin: 0 0.5em 0 0;
-}
-
-h2 img.gravatar {margin: -2px 4px -4px 0;}
-h3 img.gravatar {margin: -4px 4px -4px 0;}
-h4 img.gravatar {margin: -6px 4px -4px 0;}
-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; }
-
-/************* CodeRay styles *************/
-.syntaxhl div {display: inline;}
-.syntaxhl .line-numbers {padding: 2px 4px 2px 4px; background-color: #eee; margin:0px 5px 0px 0px;}
-.syntaxhl .code pre { overflow: auto }
-.syntaxhl .debug { color: white !important; background: blue !important; }
-
-.syntaxhl .annotation { color:#007 }
-.syntaxhl .attribute-name { color:#b48 }
-.syntaxhl .attribute-value { color:#700 }
-.syntaxhl .binary { color:#509 }
-.syntaxhl .char .content { color:#D20 }
-.syntaxhl .char .delimiter { color:#710 }
-.syntaxhl .char { color:#D20 }
-.syntaxhl .class { color:#258; font-weight:bold }
-.syntaxhl .class-variable { color:#369 }
-.syntaxhl .color { color:#0A0 }
-.syntaxhl .comment { color:#385 }
-.syntaxhl .comment .char { color:#385 }
-.syntaxhl .comment .delimiter { color:#385 }
-.syntaxhl .complex { color:#A08 }
-.syntaxhl .constant { color:#258; font-weight:bold }
-.syntaxhl .decorator { color:#B0B }
-.syntaxhl .definition { color:#099; font-weight:bold }
-.syntaxhl .delimiter { color:black }
-.syntaxhl .directive { color:#088; font-weight:bold }
-.syntaxhl .doc { color:#970 }
-.syntaxhl .doc-string { color:#D42; font-weight:bold }
-.syntaxhl .doctype { color:#34b }
-.syntaxhl .entity { color:#800; font-weight:bold }
-.syntaxhl .error { color:#F00; background-color:#FAA }
-.syntaxhl .escape { color:#666 }
-.syntaxhl .exception { color:#C00; font-weight:bold }
-.syntaxhl .float { color:#06D }
-.syntaxhl .function { color:#06B; font-weight:bold }
-.syntaxhl .global-variable { color:#d70 }
-.syntaxhl .hex { color:#02b }
-.syntaxhl .imaginary { color:#f00 }
-.syntaxhl .include { color:#B44; font-weight:bold }
-.syntaxhl .inline { background-color: hsla(0,0%,0%,0.07); color: black }
-.syntaxhl .inline-delimiter { font-weight: bold; color: #666 }
-.syntaxhl .instance-variable { color:#33B }
-.syntaxhl .integer { color:#06D }
-.syntaxhl .key .char { color: #60f }
-.syntaxhl .key .delimiter { color: #404 }
-.syntaxhl .key { color: #606 }
-.syntaxhl .keyword { color:#939; font-weight:bold }
-.syntaxhl .label { color:#970; font-weight:bold }
-.syntaxhl .local-variable { color:#963 }
-.syntaxhl .namespace { color:#707; font-weight:bold }
-.syntaxhl .octal { color:#40E }
-.syntaxhl .operator { }
-.syntaxhl .predefined { color:#369; font-weight:bold }
-.syntaxhl .predefined-constant { color:#069 }
-.syntaxhl .predefined-type { color:#0a5; font-weight:bold }
-.syntaxhl .preprocessor { color:#579 }
-.syntaxhl .pseudo-class { color:#00C; font-weight:bold }
-.syntaxhl .regexp .content { color:#808 }
-.syntaxhl .regexp .delimiter { color:#404 }
-.syntaxhl .regexp .modifier { color:#C2C }
-.syntaxhl .regexp { background-color:hsla(300,100%,50%,0.06); }
-.syntaxhl .reserved { color:#080; font-weight:bold }
-.syntaxhl .shell .content { color:#2B2 }
-.syntaxhl .shell .delimiter { color:#161 }
-.syntaxhl .shell { background-color:hsla(120,100%,50%,0.06); }
-.syntaxhl .string .char { color: #46a }
-.syntaxhl .string .content { color: #46a }
-.syntaxhl .string .delimiter { color: #46a }
-.syntaxhl .string .modifier { color: #46a }
-.syntaxhl .symbol .content { color:#d33 }
-.syntaxhl .symbol .delimiter { color:#d33 }
-.syntaxhl .symbol { color:#d33 }
-.syntaxhl .tag { color:#070 }
-.syntaxhl .type { color:#339; font-weight:bold }
-.syntaxhl .value { color: #088; }
-.syntaxhl .variable { color:#037 }
-
-.syntaxhl .insert { background: hsla(120,100%,50%,0.12) }
-.syntaxhl .delete { background: hsla(0,100%,50%,0.12) }
-.syntaxhl .change { color: #bbf; background: #007; }
-.syntaxhl .head { color: #f8f; background: #505 }
-.syntaxhl .head .filename { color: white; }
-
-.syntaxhl .delete .eyecatcher { background-color: hsla(0,100%,50%,0.2); border: 1px solid hsla(0,100%,45%,0.5); margin: -1px; border-bottom: none; border-top-left-radius: 5px; border-top-right-radius: 5px; }
-.syntaxhl .insert .eyecatcher { background-color: hsla(120,100%,50%,0.2); border: 1px solid hsla(120,100%,25%,0.5); margin: -1px; border-top: none; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }
-
-.syntaxhl .insert .insert { color: #0c0; background:transparent; font-weight:bold }
-.syntaxhl .delete .delete { color: #c00; background:transparent; font-weight:bold }
-.syntaxhl .change .change { color: #88f }
-.syntaxhl .head .head { color: #f4f }
-
-/***** 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; }
- .autoscroll {overflow-x: visible;}
- table.list {margin-top:0.5em;}
- table.list th, table.list td {border: 1px solid #aaa;}
-}
-
-/* Accessibility specific styles */
-.hidden-for-sighted {
- position:absolute;
- left:-10000px;
- top:auto;
- width:1px;
- height:1px;
- overflow:hidden;
-}
diff --git a/trustie2/public/dispatch.fcgi.example b/trustie2/public/dispatch.fcgi.example
deleted file mode 100644
index 85184c446..000000000
--- a/trustie2/public/dispatch.fcgi.example
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/env ruby
-
-require File.dirname(__FILE__) + '/../config/boot'
-require File.dirname(__FILE__) + '/../config/environment'
-
-class Rack::PathInfoRewriter
- def initialize(app)
- @app = app
- end
-
- def call(env)
- env.delete('SCRIPT_NAME')
- parts = env['REQUEST_URI'].split('?')
- env['PATH_INFO'] = parts[0]
- env['QUERY_STRING'] = parts[1].to_s
- @app.call(env)
- end
-end
-
-Rack::Handler::FastCGI.run Rack::PathInfoRewriter.new(RedmineApp::Application)
diff --git a/trustie2/public/favicon.ico b/trustie2/public/favicon.ico
deleted file mode 100644
index 75a4c3dfd..000000000
Binary files a/trustie2/public/favicon.ico and /dev/null differ
diff --git a/trustie2/public/favicon.old.ico b/trustie2/public/favicon.old.ico
deleted file mode 100644
index 51c1aeb09..000000000
Binary files a/trustie2/public/favicon.old.ico and /dev/null differ
diff --git a/trustie2/public/help/wiki_syntax.html b/trustie2/public/help/wiki_syntax.html
deleted file mode 100644
index fdae252ea..000000000
--- a/trustie2/public/help/wiki_syntax.html
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
-
-Wiki formatting
-
-
-
-
-Wiki Syntax Quick Reference
-
-
-Font Styles
-
*Strong* Strong
-
_Italic_ Italic
-
+Underline+ Underline
-
-Deleted- Deleted
-??Quote?? Quote
-
@Inline Code@ Inline Code
-
<pre>
lines
of code
</pre>
-
- lines
- of code
-
-
-
-Lists
-
* Item 1
* Item 2 - Item 1
- Item 2
-
# Item 1
# Item 2 - Item 1
- Item 2
-
-Headings
-
h1. Title 1 Title 1
-
h2. Title 2 Title 2
-
h3. Title 3 Title 3
-
-Links
-http://foo.bar http://foo.bar
-"Foo":http://foo.bar Foo
-
-Trustie links
-
[[Wiki page]] Wiki page
-Issue #12 Issue #12
-Revision r43 Revision r43
-commit:f30e13e43 f30e13e4
-source:some/file source:some/file
-
-Inline images
-
!image_url!
-!attached_image!
-
-
-
-
-
-
diff --git a/trustie2/public/help/wiki_syntax_detailed.html b/trustie2/public/help/wiki_syntax_detailed.html
deleted file mode 100644
index 2c82c3b96..000000000
--- a/trustie2/public/help/wiki_syntax_detailed.html
+++ /dev/null
@@ -1,281 +0,0 @@
-
-
-
-TrustieWikiFormatting
-
-
-
-
-
-Wiki formatting
-
- Links
-
- Trustie links
-
- Trustie allows hyperlinking between resources (issues, changesets, wiki pages...) from anywhere wiki formatting is used.
-
- - Link to an issue: #124 (displays
#124, link is striked-through if the issue is closed)
- - Link to an issue note: #124-6, or #124#note-6
-
-
- Wiki links:
-
-
- - [[Guide]] displays a link to the page named 'Guide': Guide
- - [[Guide#further-reading]] takes you to the anchor "further-reading". Headings get automatically assigned anchors so that you can refer to them: Guide
- - [[Guide|User manual]] displays a link to the same page but with a different text: User manual
-
-
- You can also link to pages of an other project wiki:
-
-
- - [[sandbox:some page]] displays a link to the page named 'Some page' of the Sandbox wiki
- - [[sandbox:]] displays a link to the Sandbox wiki main page
-
-
- Wiki links are displayed in red if the page doesn't exist yet, eg: Nonexistent page.
-
- Links to other resources:
-
-
- - Documents:
-
- - document#17 (link to document with id 17)
- - document:Greetings (link to the document with title "Greetings")
- - document:"Some document" (double quotes can be used when document title contains spaces)
- - sandbox:document:"Some document" (link to a document with title "Some document" in other project "sandbox")
-
-
-
-
- - Versions:
-
- - version#3 (link to version with id 3)
- - version:1.0.0 (link to version named "1.0.0")
- - version:"1.0 beta 2"
- - sandbox:version:1.0.0 (link to version "1.0.0" in the project "sandbox")
-
-
-
-
- - Attachments:
-
- - attachment:file.zip (link to the attachment of the current object named file.zip)
- - For now, attachments of the current object can be referenced only (if you're on an issue, it's possible to reference attachments of this issue only)
-
-
-
-
- - Changesets:
-
- - r758 (link to a changeset)
- - commit:c6f4d0fd (link to a changeset with a non-numeric hash)
- - svn1|r758 (link to a changeset of a specific repository, for projects with multiple repositories)
- - commit:hg|c6f4d0fd (link to a changeset with a non-numeric hash of a specific repository)
- - sandbox:r758 (link to a changeset of another project)
- - sandbox:commit:c6f4d0fd (link to a changeset with a non-numeric hash of another project)
-
-
-
-
- - Repository files:
-
- - source:some/file (link to the file located at /some/file in the project's repository)
- - source:some/file@52 (link to the file's revision 52)
- - source:some/file#L120 (link to line 120 of the file)
- - source:some/file@52#L120 (link to line 120 of the file's revision 52)
- - source:"some file@52#L120" (use double quotes when the URL contains spaces
- - export:some/file (force the download of the file)
- - source:svn1|some/file (link to a file of a specific repository, for projects with multiple repositories)
- - sandbox:source:some/file (link to the file located at /some/file in the repository of the project "sandbox")
- - sandbox:export:some/file (force the download of the file)
-
-
-
-
- - Forum messages:
-
- - message#1218 (link to message with id 1218)
-
-
-
-
- - Projects:
-
- - project#3 (link to project with id 3)
- - project:someproject (link to project named "someproject")
-
-
-
-
- Escaping:
-
-
- - You can prevent Trustie links from being parsed by preceding them with an exclamation mark: !
-
-
-
- External links
-
- HTTP URLs and email addresses are automatically turned into clickable links:
-
-
-http://www.trustie.org, someone@foo.bar
-
-
- displays: http://www.trustie.org, someone@foo.bar
-
- If you want to display a specific text instead of the URL, you can use the standard textile syntax:
-
-
-"Trustie web site":http://www.trustie.org
-
-
- displays: Trustie web site
-
-
- Text formatting
-
-
- For things such as headlines, bold, tables, lists, Trustie supports Textile syntax. See http://en.wikipedia.org/wiki/Textile_(markup_language) for information on using any of these features. A few samples are included below, but the engine is capable of much more of that.
-
- Font style
-
-
-* *bold*
-* _italic_
-* _*bold italic*_
-* +underline+
-* -strike-through-
-
-
- Display:
-
-
- - bold
- - italic
- - *bold italic*
- - underline
- strike-through
-
-
- Inline images
-
-
- - !image_url! displays an image located at image_url (textile syntax)
- - !>image_url! right floating image
- - If you have an image attached to your wiki page, it can be displayed inline using its filename: !attached_image.png!
-
-
- Headings
-
-
-h1. Heading
-h2. Subheading
-h3. Subsubheading
-
-
- Trustie assigns an anchor to each of those headings thus you can link to them with "#Heading", "#Subheading" and so forth.
-
-
- Paragraphs
-
-
-p>. right aligned
-p=. centered
-
-
- This is a centered paragraph.
-
-
- Blockquotes
-
- Start the paragraph with bq.
-
-
-bq. Rails is a full-stack framework for developing database-backed web applications according to the Model-View-Control pattern.
-To go live, all you need to add is a database and a web server.
-
-
- Display:
-
-
- Rails is a full-stack framework for developing database-backed web applications according to the Model-View-Control pattern.
To go live, all you need to add is a database and a web server.
-
-
-
- Table of content
-
-
-{{toc}} => left aligned toc
-{{>toc}} => right aligned toc
-
-
- Macros
-
- Trustie has the following builtin macros:
-
- hello_worldSample macro.
includeInclude a wiki page. Example:
-
- {{include(Foo)}}
macro_listDisplays a list of all available macros, including description if available.
-
-
- Code highlighting
-
- Default code highlightment relies on CodeRay, a fast syntax highlighting library written completely in Ruby. It currently supports c, cpp, css, delphi, groovy, html, java, javascript, json, php, python, rhtml, ruby, scheme, sql, xml and yaml languages.
-
- You can highlight code in your wiki page using this syntax:
-
-
-<pre><code class="ruby">
- Place you code here.
-</code></pre>
-
-
- Example:
-
- 1 # The Greeter class
- 2 class Greeter
- 3 def initialize(name)
- 4 @name = name.capitalize
- 5 end
- 6
- 7 def salute
- 8 puts "Hello #{@name}!"
- 9 end
-10 end
-
-
-
diff --git a/trustie2/public/htaccess.fcgi.example b/trustie2/public/htaccess.fcgi.example
deleted file mode 100644
index f06975d43..000000000
--- a/trustie2/public/htaccess.fcgi.example
+++ /dev/null
@@ -1,49 +0,0 @@
-# General Apache options
-
- AddHandler fastcgi-script .fcgi
-
-
- AddHandler fcgid-script .fcgi
-
-Options +FollowSymLinks +ExecCGI
-
-# If you don't want Rails to look in certain directories,
-# use the following rewrite rules so that Apache won't rewrite certain requests
-#
-# Example:
-# RewriteCond %{REQUEST_URI} ^/notrails.*
-# RewriteRule .* - [L]
-
-# Redirect all requests not available on the filesystem to Rails
-# By default the cgi dispatcher is used which is very slow
-#
-# For better performance replace the dispatcher with the fastcgi one
-#
-# Example:
-# RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
-RewriteEngine On
-
-# If your Rails application is accessed via an Alias directive,
-# then you MUST also set the RewriteBase in this htaccess file.
-#
-# Example:
-# Alias /myrailsapp /path/to/myrailsapp/public
-# RewriteBase /myrailsapp
-
-RewriteRule ^$ index.html [QSA]
-RewriteRule ^([^.]+)$ $1.html [QSA]
-RewriteCond %{REQUEST_FILENAME} !-f
-
- RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
-
-
- RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
-
-
-# In case Rails experiences terminal errors
-# Instead of displaying this message you can supply a file here which will be rendered instead
-#
-# Example:
-# ErrorDocument 500 /500.html
-
-ErrorDocument 500 "Application error
Rails application failed to start properly"
diff --git a/trustie2/public/images/007.gif b/trustie2/public/images/007.gif
deleted file mode 100644
index 16e705d92..000000000
Binary files a/trustie2/public/images/007.gif and /dev/null differ
diff --git a/trustie2/public/images/008.jpg b/trustie2/public/images/008.jpg
deleted file mode 100644
index 378e72164..000000000
Binary files a/trustie2/public/images/008.jpg and /dev/null differ
diff --git a/trustie2/public/images/009.gif b/trustie2/public/images/009.gif
deleted file mode 100644
index b90b130fb..000000000
Binary files a/trustie2/public/images/009.gif and /dev/null differ
diff --git a/trustie2/public/images/021.png b/trustie2/public/images/021.png
deleted file mode 100644
index 536464fce..000000000
Binary files a/trustie2/public/images/021.png and /dev/null differ
diff --git a/trustie2/public/images/039.gif b/trustie2/public/images/039.gif
deleted file mode 100644
index 919d667c9..000000000
Binary files a/trustie2/public/images/039.gif and /dev/null differ
diff --git a/trustie2/public/images/100.gif b/trustie2/public/images/100.gif
deleted file mode 100644
index 5e0ed3f27..000000000
Binary files a/trustie2/public/images/100.gif and /dev/null differ
diff --git a/trustie2/public/images/1000.gif b/trustie2/public/images/1000.gif
deleted file mode 100644
index 753fbb182..000000000
Binary files a/trustie2/public/images/1000.gif and /dev/null differ
diff --git a/trustie2/public/images/10000.gif b/trustie2/public/images/10000.gif
deleted file mode 100644
index 839c09744..000000000
Binary files a/trustie2/public/images/10000.gif and /dev/null differ
diff --git a/trustie2/public/images/115960_50.jpg b/trustie2/public/images/115960_50.jpg
deleted file mode 100644
index aa45853f5..000000000
Binary files a/trustie2/public/images/115960_50.jpg and /dev/null differ
diff --git a/trustie2/public/images/121944_50.jpg b/trustie2/public/images/121944_50.jpg
deleted file mode 100644
index 26e7db3e7..000000000
Binary files a/trustie2/public/images/121944_50.jpg and /dev/null differ
diff --git a/trustie2/public/images/12_50.png b/trustie2/public/images/12_50.png
deleted file mode 100644
index af618c697..000000000
Binary files a/trustie2/public/images/12_50.png and /dev/null differ
diff --git a/trustie2/public/images/1downarrow.png b/trustie2/public/images/1downarrow.png
deleted file mode 100644
index a6d07e92b..000000000
Binary files a/trustie2/public/images/1downarrow.png and /dev/null differ
diff --git a/trustie2/public/images/1uparrow.png b/trustie2/public/images/1uparrow.png
deleted file mode 100644
index 6c0eae469..000000000
Binary files a/trustie2/public/images/1uparrow.png and /dev/null differ
diff --git a/trustie2/public/images/233683_50.jpg b/trustie2/public/images/233683_50.jpg
deleted file mode 100644
index 65ef363cc..000000000
Binary files a/trustie2/public/images/233683_50.jpg and /dev/null differ
diff --git a/trustie2/public/images/28_50.jpg b/trustie2/public/images/28_50.jpg
deleted file mode 100644
index 0d2f45b63..000000000
Binary files a/trustie2/public/images/28_50.jpg and /dev/null differ
diff --git a/trustie2/public/images/2downarrow.png b/trustie2/public/images/2downarrow.png
deleted file mode 100644
index 179651689..000000000
Binary files a/trustie2/public/images/2downarrow.png and /dev/null differ
diff --git a/trustie2/public/images/2uparrow.png b/trustie2/public/images/2uparrow.png
deleted file mode 100644
index 352cc2bb9..000000000
Binary files a/trustie2/public/images/2uparrow.png and /dev/null differ
diff --git a/trustie2/public/images/47318_50.jpg b/trustie2/public/images/47318_50.jpg
deleted file mode 100644
index e825b1949..000000000
Binary files a/trustie2/public/images/47318_50.jpg and /dev/null differ
diff --git a/trustie2/public/images/737521_50.jpg b/trustie2/public/images/737521_50.jpg
deleted file mode 100644
index 68a02e4a7..000000000
Binary files a/trustie2/public/images/737521_50.jpg and /dev/null differ
diff --git a/trustie2/public/images/860270_50.jpg b/trustie2/public/images/860270_50.jpg
deleted file mode 100644
index beea14904..000000000
Binary files a/trustie2/public/images/860270_50.jpg and /dev/null differ
diff --git a/trustie2/public/images/926055_50.jpg b/trustie2/public/images/926055_50.jpg
deleted file mode 100644
index 90e0e8474..000000000
Binary files a/trustie2/public/images/926055_50.jpg and /dev/null differ
diff --git a/trustie2/public/images/TOP100.gif b/trustie2/public/images/TOP100.gif
deleted file mode 100644
index bc2ebea60..000000000
Binary files a/trustie2/public/images/TOP100.gif and /dev/null differ
diff --git a/trustie2/public/images/TOP1000.gif b/trustie2/public/images/TOP1000.gif
deleted file mode 100644
index 6d122c413..000000000
Binary files a/trustie2/public/images/TOP1000.gif and /dev/null differ
diff --git a/trustie2/public/images/TOP10000.gif b/trustie2/public/images/TOP10000.gif
deleted file mode 100644
index 1b6492791..000000000
Binary files a/trustie2/public/images/TOP10000.gif and /dev/null differ
diff --git a/trustie2/public/images/add.png b/trustie2/public/images/add.png
deleted file mode 100644
index d6d26db7c..000000000
Binary files a/trustie2/public/images/add.png and /dev/null differ
diff --git a/trustie2/public/images/add_enterprise.png b/trustie2/public/images/add_enterprise.png
deleted file mode 100644
index 0a9ae4abe..000000000
Binary files a/trustie2/public/images/add_enterprise.png and /dev/null differ
diff --git a/trustie2/public/images/android_0.jpg b/trustie2/public/images/android_0.jpg
deleted file mode 100644
index 6aadab331..000000000
Binary files a/trustie2/public/images/android_0.jpg and /dev/null differ
diff --git a/trustie2/public/images/app1.png b/trustie2/public/images/app1.png
deleted file mode 100644
index 3342781ac..000000000
Binary files a/trustie2/public/images/app1.png and /dev/null differ
diff --git a/trustie2/public/images/arrow_collapsed.png b/trustie2/public/images/arrow_collapsed.png
deleted file mode 100644
index cbcc70ded..000000000
Binary files a/trustie2/public/images/arrow_collapsed.png and /dev/null differ
diff --git a/trustie2/public/images/arrow_down.png b/trustie2/public/images/arrow_down.png
deleted file mode 100644
index 7a2a1a353..000000000
Binary files a/trustie2/public/images/arrow_down.png and /dev/null differ
diff --git a/trustie2/public/images/arrow_expanded.png b/trustie2/public/images/arrow_expanded.png
deleted file mode 100644
index 7b1c563bf..000000000
Binary files a/trustie2/public/images/arrow_expanded.png and /dev/null differ
diff --git a/trustie2/public/images/attachment.png b/trustie2/public/images/attachment.png
deleted file mode 100644
index 3762eafec..000000000
Binary files a/trustie2/public/images/attachment.png and /dev/null differ
diff --git a/trustie2/public/images/avatars/AnonymousUser/0 b/trustie2/public/images/avatars/AnonymousUser/0
deleted file mode 100644
index a4cc45467..000000000
Binary files a/trustie2/public/images/avatars/AnonymousUser/0 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/0 b/trustie2/public/images/avatars/Project/0
deleted file mode 100644
index 585b4bfc0..000000000
Binary files a/trustie2/public/images/avatars/Project/0 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/6314 b/trustie2/public/images/avatars/Project/6314
deleted file mode 100644
index b58caabfa..000000000
Binary files a/trustie2/public/images/avatars/Project/6314 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/6315 b/trustie2/public/images/avatars/Project/6315
deleted file mode 100644
index cce3b9ccf..000000000
Binary files a/trustie2/public/images/avatars/Project/6315 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/6316 b/trustie2/public/images/avatars/Project/6316
deleted file mode 100644
index fa4fd4110..000000000
Binary files a/trustie2/public/images/avatars/Project/6316 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/6322 b/trustie2/public/images/avatars/Project/6322
deleted file mode 100644
index 1f0332907..000000000
Binary files a/trustie2/public/images/avatars/Project/6322 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/6330 b/trustie2/public/images/avatars/Project/6330
deleted file mode 100644
index 030ab8a68..000000000
Binary files a/trustie2/public/images/avatars/Project/6330 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/6356 b/trustie2/public/images/avatars/Project/6356
deleted file mode 100644
index 757c2a628..000000000
Binary files a/trustie2/public/images/avatars/Project/6356 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/6358 b/trustie2/public/images/avatars/Project/6358
deleted file mode 100644
index 030ab8a68..000000000
Binary files a/trustie2/public/images/avatars/Project/6358 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/6408 b/trustie2/public/images/avatars/Project/6408
deleted file mode 100644
index bf740e537..000000000
Binary files a/trustie2/public/images/avatars/Project/6408 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/6446 b/trustie2/public/images/avatars/Project/6446
deleted file mode 100644
index 90e0e8474..000000000
Binary files a/trustie2/public/images/avatars/Project/6446 and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/course.jpg b/trustie2/public/images/avatars/Project/course.jpg
deleted file mode 100644
index 81b0e925c..000000000
Binary files a/trustie2/public/images/avatars/Project/course.jpg and /dev/null differ
diff --git a/trustie2/public/images/avatars/Project/no_profile.png b/trustie2/public/images/avatars/Project/no_profile.png
deleted file mode 100644
index 7640e017a..000000000
Binary files a/trustie2/public/images/avatars/Project/no_profile.png and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/0 b/trustie2/public/images/avatars/User/0
deleted file mode 100644
index a4cc45467..000000000
Binary files a/trustie2/public/images/avatars/User/0 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/1 b/trustie2/public/images/avatars/User/1
deleted file mode 100644
index 090de2290..000000000
Binary files a/trustie2/public/images/avatars/User/1 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4245 b/trustie2/public/images/avatars/User/4245
deleted file mode 100644
index 8057fac14..000000000
Binary files a/trustie2/public/images/avatars/User/4245 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4246 b/trustie2/public/images/avatars/User/4246
deleted file mode 100644
index 757c2a628..000000000
Binary files a/trustie2/public/images/avatars/User/4246 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4247 b/trustie2/public/images/avatars/User/4247
deleted file mode 100644
index 3df1c4e68..000000000
Binary files a/trustie2/public/images/avatars/User/4247 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4249 b/trustie2/public/images/avatars/User/4249
deleted file mode 100644
index 93600eb8f..000000000
Binary files a/trustie2/public/images/avatars/User/4249 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4275 b/trustie2/public/images/avatars/User/4275
deleted file mode 100644
index 2659a14b7..000000000
Binary files a/trustie2/public/images/avatars/User/4275 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4288 b/trustie2/public/images/avatars/User/4288
deleted file mode 100644
index ca17e5328..000000000
Binary files a/trustie2/public/images/avatars/User/4288 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4856 b/trustie2/public/images/avatars/User/4856
deleted file mode 100644
index 96d1098fd..000000000
Binary files a/trustie2/public/images/avatars/User/4856 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4858 b/trustie2/public/images/avatars/User/4858
deleted file mode 100644
index 8df8790ba..000000000
Binary files a/trustie2/public/images/avatars/User/4858 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4859 b/trustie2/public/images/avatars/User/4859
deleted file mode 100644
index 78704a099..000000000
Binary files a/trustie2/public/images/avatars/User/4859 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4861 b/trustie2/public/images/avatars/User/4861
deleted file mode 100644
index a587c9656..000000000
Binary files a/trustie2/public/images/avatars/User/4861 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4863 b/trustie2/public/images/avatars/User/4863
deleted file mode 100644
index 26e7db3e7..000000000
Binary files a/trustie2/public/images/avatars/User/4863 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4869 b/trustie2/public/images/avatars/User/4869
deleted file mode 100644
index 030ab8a68..000000000
Binary files a/trustie2/public/images/avatars/User/4869 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4874 b/trustie2/public/images/avatars/User/4874
deleted file mode 100644
index 90e0e8474..000000000
Binary files a/trustie2/public/images/avatars/User/4874 and /dev/null differ
diff --git a/trustie2/public/images/avatars/User/4896 b/trustie2/public/images/avatars/User/4896
deleted file mode 100644
index 757c2a628..000000000
Binary files a/trustie2/public/images/avatars/User/4896 and /dev/null differ
diff --git a/trustie2/public/images/bid/A.jpg b/trustie2/public/images/bid/A.jpg
deleted file mode 100644
index 22ddd2044..000000000
Binary files a/trustie2/public/images/bid/A.jpg and /dev/null differ
diff --git a/trustie2/public/images/bid/B+.jpg b/trustie2/public/images/bid/B+.jpg
deleted file mode 100644
index 93c5a605f..000000000
Binary files a/trustie2/public/images/bid/B+.jpg and /dev/null differ
diff --git a/trustie2/public/images/bid/B.jpg b/trustie2/public/images/bid/B.jpg
deleted file mode 100644
index 318591acc..000000000
Binary files a/trustie2/public/images/bid/B.jpg and /dev/null differ
diff --git a/trustie2/public/images/bid/C+.jpg b/trustie2/public/images/bid/C+.jpg
deleted file mode 100644
index 2764d9ee3..000000000
Binary files a/trustie2/public/images/bid/C+.jpg and /dev/null differ
diff --git a/trustie2/public/images/bid/C.jpg b/trustie2/public/images/bid/C.jpg
deleted file mode 100644
index 4627a2940..000000000
Binary files a/trustie2/public/images/bid/C.jpg and /dev/null differ
diff --git a/trustie2/public/images/bid/D+.jpg b/trustie2/public/images/bid/D+.jpg
deleted file mode 100644
index 41064a55e..000000000
Binary files a/trustie2/public/images/bid/D+.jpg and /dev/null differ
diff --git a/trustie2/public/images/bid/D.jpg b/trustie2/public/images/bid/D.jpg
deleted file mode 100644
index 2c04b85c4..000000000
Binary files a/trustie2/public/images/bid/D.jpg and /dev/null differ
diff --git a/trustie2/public/images/bid/E+.png b/trustie2/public/images/bid/E+.png
deleted file mode 100644
index 1dabdac97..000000000
Binary files a/trustie2/public/images/bid/E+.png and /dev/null differ
diff --git a/trustie2/public/images/bid/E.png b/trustie2/public/images/bid/E.png
deleted file mode 100644
index 0da3aca35..000000000
Binary files a/trustie2/public/images/bid/E.png and /dev/null differ
diff --git a/trustie2/public/images/bid/F.jpg b/trustie2/public/images/bid/F.jpg
deleted file mode 100644
index 3550db277..000000000
Binary files a/trustie2/public/images/bid/F.jpg and /dev/null differ
diff --git a/trustie2/public/images/bid/award.png b/trustie2/public/images/bid/award.png
deleted file mode 100644
index 9f407fca9..000000000
Binary files a/trustie2/public/images/bid/award.png and /dev/null differ
diff --git a/trustie2/public/images/bid/candidate.png b/trustie2/public/images/bid/candidate.png
deleted file mode 100644
index a08e8bed4..000000000
Binary files a/trustie2/public/images/bid/candidate.png and /dev/null differ
diff --git a/trustie2/public/images/bid/fifth_reward.png b/trustie2/public/images/bid/fifth_reward.png
deleted file mode 100644
index ae7b87718..000000000
Binary files a/trustie2/public/images/bid/fifth_reward.png and /dev/null differ
diff --git a/trustie2/public/images/bid/first_reward.png b/trustie2/public/images/bid/first_reward.png
deleted file mode 100644
index 06765279e..000000000
Binary files a/trustie2/public/images/bid/first_reward.png and /dev/null differ
diff --git a/trustie2/public/images/bid/forth_reward.png b/trustie2/public/images/bid/forth_reward.png
deleted file mode 100644
index f6ffadd74..000000000
Binary files a/trustie2/public/images/bid/forth_reward.png and /dev/null differ
diff --git a/trustie2/public/images/bid/obsolete.png b/trustie2/public/images/bid/obsolete.png
deleted file mode 100644
index a907dd9e8..000000000
Binary files a/trustie2/public/images/bid/obsolete.png and /dev/null differ
diff --git a/trustie2/public/images/bid/qualified.png b/trustie2/public/images/bid/qualified.png
deleted file mode 100644
index 6b3f1efdb..000000000
Binary files a/trustie2/public/images/bid/qualified.png and /dev/null differ
diff --git a/trustie2/public/images/bid/second_reward.png b/trustie2/public/images/bid/second_reward.png
deleted file mode 100644
index e7ab9d4ee..000000000
Binary files a/trustie2/public/images/bid/second_reward.png and /dev/null differ
diff --git a/trustie2/public/images/bid/special_reward.png b/trustie2/public/images/bid/special_reward.png
deleted file mode 100644
index a3a4df593..000000000
Binary files a/trustie2/public/images/bid/special_reward.png and /dev/null differ
diff --git a/trustie2/public/images/bid/third_reward.png b/trustie2/public/images/bid/third_reward.png
deleted file mode 100644
index 8dc6f37d2..000000000
Binary files a/trustie2/public/images/bid/third_reward.png and /dev/null differ
diff --git a/trustie2/public/images/bid/win_bid.png b/trustie2/public/images/bid/win_bid.png
deleted file mode 100644
index 5cafbb88d..000000000
Binary files a/trustie2/public/images/bid/win_bid.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_add.png b/trustie2/public/images/bullet_add.png
deleted file mode 100644
index a3f850dcc..000000000
Binary files a/trustie2/public/images/bullet_add.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_arrow_left.png b/trustie2/public/images/bullet_arrow_left.png
deleted file mode 100644
index cabc1d79f..000000000
Binary files a/trustie2/public/images/bullet_arrow_left.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_arrow_right.png b/trustie2/public/images/bullet_arrow_right.png
deleted file mode 100644
index cbcc70ded..000000000
Binary files a/trustie2/public/images/bullet_arrow_right.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_black.png b/trustie2/public/images/bullet_black.png
deleted file mode 100644
index 6d87f99a9..000000000
Binary files a/trustie2/public/images/bullet_black.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_blue.png b/trustie2/public/images/bullet_blue.png
deleted file mode 100644
index 79d978c36..000000000
Binary files a/trustie2/public/images/bullet_blue.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_delete.png b/trustie2/public/images/bullet_delete.png
deleted file mode 100644
index 3459293cb..000000000
Binary files a/trustie2/public/images/bullet_delete.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_diamond.png b/trustie2/public/images/bullet_diamond.png
deleted file mode 100644
index f68cb7958..000000000
Binary files a/trustie2/public/images/bullet_diamond.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_end.png b/trustie2/public/images/bullet_end.png
deleted file mode 100644
index 0ff03323f..000000000
Binary files a/trustie2/public/images/bullet_end.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_go.png b/trustie2/public/images/bullet_go.png
deleted file mode 100644
index c724754b3..000000000
Binary files a/trustie2/public/images/bullet_go.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_orange.png b/trustie2/public/images/bullet_orange.png
deleted file mode 100644
index d4b3cd05e..000000000
Binary files a/trustie2/public/images/bullet_orange.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_purple.png b/trustie2/public/images/bullet_purple.png
deleted file mode 100644
index 58bc636bc..000000000
Binary files a/trustie2/public/images/bullet_purple.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_toggle_minus.png b/trustie2/public/images/bullet_toggle_minus.png
deleted file mode 100644
index 656fc9ce4..000000000
Binary files a/trustie2/public/images/bullet_toggle_minus.png and /dev/null differ
diff --git a/trustie2/public/images/bullet_toggle_plus.png b/trustie2/public/images/bullet_toggle_plus.png
deleted file mode 100644
index bbd81a90b..000000000
Binary files a/trustie2/public/images/bullet_toggle_plus.png and /dev/null differ
diff --git a/trustie2/public/images/button/Thumbs.db b/trustie2/public/images/button/Thumbs.db
deleted file mode 100644
index 26c0ae67c..000000000
Binary files a/trustie2/public/images/button/Thumbs.db and /dev/null differ
diff --git a/trustie2/public/images/button/bg1.jpg b/trustie2/public/images/button/bg1.jpg
deleted file mode 100644
index 0e73b2c10..000000000
Binary files a/trustie2/public/images/button/bg1.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg10.jpg b/trustie2/public/images/button/bg10.jpg
deleted file mode 100644
index f0bdb03cc..000000000
Binary files a/trustie2/public/images/button/bg10.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg100.jpg b/trustie2/public/images/button/bg100.jpg
deleted file mode 100644
index 3eb9490e7..000000000
Binary files a/trustie2/public/images/button/bg100.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg102.jpg b/trustie2/public/images/button/bg102.jpg
deleted file mode 100644
index e43cde964..000000000
Binary files a/trustie2/public/images/button/bg102.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg103.jpg b/trustie2/public/images/button/bg103.jpg
deleted file mode 100644
index 411901ef4..000000000
Binary files a/trustie2/public/images/button/bg103.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg104.jpg b/trustie2/public/images/button/bg104.jpg
deleted file mode 100644
index e3278442a..000000000
Binary files a/trustie2/public/images/button/bg104.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg105.jpg b/trustie2/public/images/button/bg105.jpg
deleted file mode 100644
index 7bf611367..000000000
Binary files a/trustie2/public/images/button/bg105.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg106.jpg b/trustie2/public/images/button/bg106.jpg
deleted file mode 100644
index 5db4c7223..000000000
Binary files a/trustie2/public/images/button/bg106.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg11.jpg b/trustie2/public/images/button/bg11.jpg
deleted file mode 100644
index f730edfeb..000000000
Binary files a/trustie2/public/images/button/bg11.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg12.jpg b/trustie2/public/images/button/bg12.jpg
deleted file mode 100644
index 2e598b59b..000000000
Binary files a/trustie2/public/images/button/bg12.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg13.jpg b/trustie2/public/images/button/bg13.jpg
deleted file mode 100644
index 38bc2b5f2..000000000
Binary files a/trustie2/public/images/button/bg13.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg16.jpg b/trustie2/public/images/button/bg16.jpg
deleted file mode 100644
index 648b234a6..000000000
Binary files a/trustie2/public/images/button/bg16.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg17.jpg b/trustie2/public/images/button/bg17.jpg
deleted file mode 100644
index 4985ac9a4..000000000
Binary files a/trustie2/public/images/button/bg17.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg18.jpg b/trustie2/public/images/button/bg18.jpg
deleted file mode 100644
index b4f8f3fe6..000000000
Binary files a/trustie2/public/images/button/bg18.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg19.jpg b/trustie2/public/images/button/bg19.jpg
deleted file mode 100644
index c6278a1e1..000000000
Binary files a/trustie2/public/images/button/bg19.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg2.jpg b/trustie2/public/images/button/bg2.jpg
deleted file mode 100644
index 16bb498b5..000000000
Binary files a/trustie2/public/images/button/bg2.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg20.jpg b/trustie2/public/images/button/bg20.jpg
deleted file mode 100644
index 325fd5f5e..000000000
Binary files a/trustie2/public/images/button/bg20.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg21.jpg b/trustie2/public/images/button/bg21.jpg
deleted file mode 100644
index e7739f0ab..000000000
Binary files a/trustie2/public/images/button/bg21.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg22.jpg b/trustie2/public/images/button/bg22.jpg
deleted file mode 100644
index 2262fab1f..000000000
Binary files a/trustie2/public/images/button/bg22.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg23.jpg b/trustie2/public/images/button/bg23.jpg
deleted file mode 100644
index 9d0ab8be5..000000000
Binary files a/trustie2/public/images/button/bg23.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg24.jpg b/trustie2/public/images/button/bg24.jpg
deleted file mode 100644
index 6943cd306..000000000
Binary files a/trustie2/public/images/button/bg24.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg25.jpg b/trustie2/public/images/button/bg25.jpg
deleted file mode 100644
index c9a196583..000000000
Binary files a/trustie2/public/images/button/bg25.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg26.jpg b/trustie2/public/images/button/bg26.jpg
deleted file mode 100644
index b1bd753e5..000000000
Binary files a/trustie2/public/images/button/bg26.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg27.jpg b/trustie2/public/images/button/bg27.jpg
deleted file mode 100644
index d7587dc25..000000000
Binary files a/trustie2/public/images/button/bg27.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg28.jpg b/trustie2/public/images/button/bg28.jpg
deleted file mode 100644
index 67fe5b9c1..000000000
Binary files a/trustie2/public/images/button/bg28.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg29.jpg b/trustie2/public/images/button/bg29.jpg
deleted file mode 100644
index 44ffc34f1..000000000
Binary files a/trustie2/public/images/button/bg29.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg3.jpg b/trustie2/public/images/button/bg3.jpg
deleted file mode 100644
index 2a0dacd4a..000000000
Binary files a/trustie2/public/images/button/bg3.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg30.jpg b/trustie2/public/images/button/bg30.jpg
deleted file mode 100644
index 5b9b477da..000000000
Binary files a/trustie2/public/images/button/bg30.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg31.jpg b/trustie2/public/images/button/bg31.jpg
deleted file mode 100644
index e32b01c2b..000000000
Binary files a/trustie2/public/images/button/bg31.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg32.jpg b/trustie2/public/images/button/bg32.jpg
deleted file mode 100644
index 4573d1711..000000000
Binary files a/trustie2/public/images/button/bg32.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg33.jpg b/trustie2/public/images/button/bg33.jpg
deleted file mode 100644
index 44c1bc118..000000000
Binary files a/trustie2/public/images/button/bg33.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg34.jpg b/trustie2/public/images/button/bg34.jpg
deleted file mode 100644
index e593973f5..000000000
Binary files a/trustie2/public/images/button/bg34.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg35.jpg b/trustie2/public/images/button/bg35.jpg
deleted file mode 100644
index 3773bc94b..000000000
Binary files a/trustie2/public/images/button/bg35.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg36.jpg b/trustie2/public/images/button/bg36.jpg
deleted file mode 100644
index 429316707..000000000
Binary files a/trustie2/public/images/button/bg36.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg37.jpg b/trustie2/public/images/button/bg37.jpg
deleted file mode 100644
index 286a30230..000000000
Binary files a/trustie2/public/images/button/bg37.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg38.jpg b/trustie2/public/images/button/bg38.jpg
deleted file mode 100644
index 9f168959b..000000000
Binary files a/trustie2/public/images/button/bg38.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg39.jpg b/trustie2/public/images/button/bg39.jpg
deleted file mode 100644
index eda5526b1..000000000
Binary files a/trustie2/public/images/button/bg39.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg40.jpg b/trustie2/public/images/button/bg40.jpg
deleted file mode 100644
index 012756f14..000000000
Binary files a/trustie2/public/images/button/bg40.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg41.jpg b/trustie2/public/images/button/bg41.jpg
deleted file mode 100644
index 23652c484..000000000
Binary files a/trustie2/public/images/button/bg41.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg42.jpg b/trustie2/public/images/button/bg42.jpg
deleted file mode 100644
index 047abccb5..000000000
Binary files a/trustie2/public/images/button/bg42.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg43.jpg b/trustie2/public/images/button/bg43.jpg
deleted file mode 100644
index 076f32c9a..000000000
Binary files a/trustie2/public/images/button/bg43.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg44.jpg b/trustie2/public/images/button/bg44.jpg
deleted file mode 100644
index f34dd1832..000000000
Binary files a/trustie2/public/images/button/bg44.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg45.jpg b/trustie2/public/images/button/bg45.jpg
deleted file mode 100644
index 338418c03..000000000
Binary files a/trustie2/public/images/button/bg45.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg46.jpg b/trustie2/public/images/button/bg46.jpg
deleted file mode 100644
index 883101d6f..000000000
Binary files a/trustie2/public/images/button/bg46.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg47.jpg b/trustie2/public/images/button/bg47.jpg
deleted file mode 100644
index f6dd6eb1e..000000000
Binary files a/trustie2/public/images/button/bg47.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg48.jpg b/trustie2/public/images/button/bg48.jpg
deleted file mode 100644
index 812617e8d..000000000
Binary files a/trustie2/public/images/button/bg48.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg49.jpg b/trustie2/public/images/button/bg49.jpg
deleted file mode 100644
index 635374f2a..000000000
Binary files a/trustie2/public/images/button/bg49.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg50.jpg b/trustie2/public/images/button/bg50.jpg
deleted file mode 100644
index 7556c947d..000000000
Binary files a/trustie2/public/images/button/bg50.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/bg7.jpg b/trustie2/public/images/button/bg7.jpg
deleted file mode 100644
index c6b13ecf5..000000000
Binary files a/trustie2/public/images/button/bg7.jpg and /dev/null differ
diff --git a/trustie2/public/images/button/css-logo.gif b/trustie2/public/images/button/css-logo.gif
deleted file mode 100644
index 82f8c3276..000000000
Binary files a/trustie2/public/images/button/css-logo.gif and /dev/null differ
diff --git a/trustie2/public/images/button/delete.gif b/trustie2/public/images/button/delete.gif
deleted file mode 100644
index 05f41fcf9..000000000
Binary files a/trustie2/public/images/button/delete.gif and /dev/null differ
diff --git a/trustie2/public/images/button/dl.png b/trustie2/public/images/button/dl.png
deleted file mode 100644
index 43b6ca486..000000000
Binary files a/trustie2/public/images/button/dl.png and /dev/null differ
diff --git a/trustie2/public/images/button/download.png b/trustie2/public/images/button/download.png
deleted file mode 100644
index 1588a5af4..000000000
Binary files a/trustie2/public/images/button/download.png and /dev/null differ
diff --git a/trustie2/public/images/button/download_focus.png b/trustie2/public/images/button/download_focus.png
deleted file mode 100644
index 5bad4fc6b..000000000
Binary files a/trustie2/public/images/button/download_focus.png and /dev/null differ
diff --git a/trustie2/public/images/button/favorite.gif b/trustie2/public/images/button/favorite.gif
deleted file mode 100644
index a8551b545..000000000
Binary files a/trustie2/public/images/button/favorite.gif and /dev/null differ
diff --git a/trustie2/public/images/button/help.gif b/trustie2/public/images/button/help.gif
deleted file mode 100644
index 75f221f4b..000000000
Binary files a/trustie2/public/images/button/help.gif and /dev/null differ
diff --git a/trustie2/public/images/button/ok.gif b/trustie2/public/images/button/ok.gif
deleted file mode 100644
index d0e539a79..000000000
Binary files a/trustie2/public/images/button/ok.gif and /dev/null differ
diff --git a/trustie2/public/images/button/register.gif b/trustie2/public/images/button/register.gif
deleted file mode 100644
index 11b9af1d2..000000000
Binary files a/trustie2/public/images/button/register.gif and /dev/null differ
diff --git a/trustie2/public/images/button/reset.gif b/trustie2/public/images/button/reset.gif
deleted file mode 100644
index 226cb2f37..000000000
Binary files a/trustie2/public/images/button/reset.gif and /dev/null differ
diff --git a/trustie2/public/images/button/submit1.gif b/trustie2/public/images/button/submit1.gif
deleted file mode 100644
index add821bfe..000000000
Binary files a/trustie2/public/images/button/submit1.gif and /dev/null differ
diff --git a/trustie2/public/images/button/submit2.gif b/trustie2/public/images/button/submit2.gif
deleted file mode 100644
index d787ee0be..000000000
Binary files a/trustie2/public/images/button/submit2.gif and /dev/null differ
diff --git a/trustie2/public/images/button/submit3.gif b/trustie2/public/images/button/submit3.gif
deleted file mode 100644
index 24a9cc36f..000000000
Binary files a/trustie2/public/images/button/submit3.gif and /dev/null differ
diff --git a/trustie2/public/images/calendar.png b/trustie2/public/images/calendar.png
deleted file mode 100644
index 62df31c93..000000000
Binary files a/trustie2/public/images/calendar.png and /dev/null differ
diff --git a/trustie2/public/images/cancel.png b/trustie2/public/images/cancel.png
deleted file mode 100644
index a98e53705..000000000
Binary files a/trustie2/public/images/cancel.png and /dev/null differ
diff --git a/trustie2/public/images/changeset.png b/trustie2/public/images/changeset.png
deleted file mode 100644
index 8bf76fbbe..000000000
Binary files a/trustie2/public/images/changeset.png and /dev/null differ
diff --git a/trustie2/public/images/close.png b/trustie2/public/images/close.png
deleted file mode 100644
index 3dd76e69c..000000000
Binary files a/trustie2/public/images/close.png and /dev/null differ
diff --git a/trustie2/public/images/close_hl.png b/trustie2/public/images/close_hl.png
deleted file mode 100644
index b7667aa80..000000000
Binary files a/trustie2/public/images/close_hl.png and /dev/null differ
diff --git a/trustie2/public/images/comment.png b/trustie2/public/images/comment.png
deleted file mode 100644
index 0e848cc07..000000000
Binary files a/trustie2/public/images/comment.png and /dev/null differ
diff --git a/trustie2/public/images/comments.png b/trustie2/public/images/comments.png
deleted file mode 100644
index ef57fdd15..000000000
Binary files a/trustie2/public/images/comments.png and /dev/null differ
diff --git a/trustie2/public/images/contest1.png b/trustie2/public/images/contest1.png
deleted file mode 100644
index 486ea3c3a..000000000
Binary files a/trustie2/public/images/contest1.png and /dev/null differ
diff --git a/trustie2/public/images/copy.png b/trustie2/public/images/copy.png
deleted file mode 100644
index 689f251cf..000000000
Binary files a/trustie2/public/images/copy.png and /dev/null differ
diff --git a/trustie2/public/images/database_key.png b/trustie2/public/images/database_key.png
deleted file mode 100644
index 107e34e5b..000000000
Binary files a/trustie2/public/images/database_key.png and /dev/null differ
diff --git a/trustie2/public/images/delete.png b/trustie2/public/images/delete.png
deleted file mode 100644
index ba6256dd5..000000000
Binary files a/trustie2/public/images/delete.png and /dev/null differ
diff --git a/trustie2/public/images/document.png b/trustie2/public/images/document.png
deleted file mode 100644
index eb22f4c08..000000000
Binary files a/trustie2/public/images/document.png and /dev/null differ
diff --git a/trustie2/public/images/down_hand.png b/trustie2/public/images/down_hand.png
deleted file mode 100644
index 627fffad4..000000000
Binary files a/trustie2/public/images/down_hand.png and /dev/null differ
diff --git a/trustie2/public/images/down_hand_after_click.png b/trustie2/public/images/down_hand_after_click.png
deleted file mode 100644
index f6f013d95..000000000
Binary files a/trustie2/public/images/down_hand_after_click.png and /dev/null differ
diff --git a/trustie2/public/images/draft.png b/trustie2/public/images/draft.png
deleted file mode 100644
index b51b07b38..000000000
Binary files a/trustie2/public/images/draft.png and /dev/null differ
diff --git a/trustie2/public/images/duplicate.png b/trustie2/public/images/duplicate.png
deleted file mode 100644
index f7d159e5c..000000000
Binary files a/trustie2/public/images/duplicate.png and /dev/null differ
diff --git a/trustie2/public/images/edit.png b/trustie2/public/images/edit.png
deleted file mode 100644
index 8335716fd..000000000
Binary files a/trustie2/public/images/edit.png and /dev/null differ
diff --git a/trustie2/public/images/edit/edit.png b/trustie2/public/images/edit/edit.png
deleted file mode 100644
index 8335716fd..000000000
Binary files a/trustie2/public/images/edit/edit.png and /dev/null differ
diff --git a/trustie2/public/images/exclamation.png b/trustie2/public/images/exclamation.png
deleted file mode 100644
index 7bd84f7a3..000000000
Binary files a/trustie2/public/images/exclamation.png and /dev/null differ
diff --git a/trustie2/public/images/external.png b/trustie2/public/images/external.png
deleted file mode 100644
index 77c202895..000000000
Binary files a/trustie2/public/images/external.png and /dev/null differ
diff --git a/trustie2/public/images/false.png b/trustie2/public/images/false.png
deleted file mode 100644
index ec01ecd32..000000000
Binary files a/trustie2/public/images/false.png and /dev/null differ
diff --git a/trustie2/public/images/fav.png b/trustie2/public/images/fav.png
deleted file mode 100644
index eb43df937..000000000
Binary files a/trustie2/public/images/fav.png and /dev/null differ
diff --git a/trustie2/public/images/fav_off.png b/trustie2/public/images/fav_off.png
deleted file mode 100644
index 51372e3fc..000000000
Binary files a/trustie2/public/images/fav_off.png and /dev/null differ
diff --git a/trustie2/public/images/feature.png b/trustie2/public/images/feature.png
deleted file mode 100644
index 1348b6507..000000000
Binary files a/trustie2/public/images/feature.png and /dev/null differ
diff --git a/trustie2/public/images/feed.png b/trustie2/public/images/feed.png
deleted file mode 100644
index 23160c348..000000000
Binary files a/trustie2/public/images/feed.png and /dev/null differ
diff --git a/trustie2/public/images/files/c.png b/trustie2/public/images/files/c.png
deleted file mode 100644
index 0dff8cfdf..000000000
Binary files a/trustie2/public/images/files/c.png and /dev/null differ
diff --git a/trustie2/public/images/files/csharp.png b/trustie2/public/images/files/csharp.png
deleted file mode 100644
index 093b1c5e3..000000000
Binary files a/trustie2/public/images/files/csharp.png and /dev/null differ
diff --git a/trustie2/public/images/files/css.png b/trustie2/public/images/files/css.png
deleted file mode 100644
index 06a17cd8c..000000000
Binary files a/trustie2/public/images/files/css.png and /dev/null differ
diff --git a/trustie2/public/images/files/default.png b/trustie2/public/images/files/default.png
deleted file mode 100644
index 22996cd9d..000000000
Binary files a/trustie2/public/images/files/default.png and /dev/null differ
diff --git a/trustie2/public/images/files/html.png b/trustie2/public/images/files/html.png
deleted file mode 100644
index 6ed2490ed..000000000
Binary files a/trustie2/public/images/files/html.png and /dev/null differ
diff --git a/trustie2/public/images/files/image.png b/trustie2/public/images/files/image.png
deleted file mode 100644
index 8954d2a55..000000000
Binary files a/trustie2/public/images/files/image.png and /dev/null differ
diff --git a/trustie2/public/images/files/java.png b/trustie2/public/images/files/java.png
deleted file mode 100644
index 0a7d6f4a6..000000000
Binary files a/trustie2/public/images/files/java.png and /dev/null differ
diff --git a/trustie2/public/images/files/js.png b/trustie2/public/images/files/js.png
deleted file mode 100644
index 0125edfa9..000000000
Binary files a/trustie2/public/images/files/js.png and /dev/null differ
diff --git a/trustie2/public/images/files/pdf.png b/trustie2/public/images/files/pdf.png
deleted file mode 100644
index 544e0d877..000000000
Binary files a/trustie2/public/images/files/pdf.png and /dev/null differ
diff --git a/trustie2/public/images/files/php.png b/trustie2/public/images/files/php.png
deleted file mode 100644
index 26f2e4d7a..000000000
Binary files a/trustie2/public/images/files/php.png and /dev/null differ
diff --git a/trustie2/public/images/files/ruby.png b/trustie2/public/images/files/ruby.png
deleted file mode 100644
index 95fb3afed..000000000
Binary files a/trustie2/public/images/files/ruby.png and /dev/null differ
diff --git a/trustie2/public/images/files/text.png b/trustie2/public/images/files/text.png
deleted file mode 100644
index b880900bf..000000000
Binary files a/trustie2/public/images/files/text.png and /dev/null differ
diff --git a/trustie2/public/images/files/xml.png b/trustie2/public/images/files/xml.png
deleted file mode 100644
index b1b61b5fe..000000000
Binary files a/trustie2/public/images/files/xml.png and /dev/null differ
diff --git a/trustie2/public/images/files/zip.png b/trustie2/public/images/files/zip.png
deleted file mode 100644
index 914fcc402..000000000
Binary files a/trustie2/public/images/files/zip.png and /dev/null differ
diff --git a/trustie2/public/images/folder.png b/trustie2/public/images/folder.png
deleted file mode 100644
index e20d6823c..000000000
Binary files a/trustie2/public/images/folder.png and /dev/null differ
diff --git a/trustie2/public/images/folder_open.png b/trustie2/public/images/folder_open.png
deleted file mode 100644
index 9d1e90d2c..000000000
Binary files a/trustie2/public/images/folder_open.png and /dev/null differ
diff --git a/trustie2/public/images/folder_open_add.png b/trustie2/public/images/folder_open_add.png
deleted file mode 100644
index 6fe9e0322..000000000
Binary files a/trustie2/public/images/folder_open_add.png and /dev/null differ
diff --git a/trustie2/public/images/folder_open_orange.png b/trustie2/public/images/folder_open_orange.png
deleted file mode 100644
index ee6504a90..000000000
Binary files a/trustie2/public/images/folder_open_orange.png and /dev/null differ
diff --git a/trustie2/public/images/footer_logo/buaa_scse.png b/trustie2/public/images/footer_logo/buaa_scse.png
deleted file mode 100644
index c224a5668..000000000
Binary files a/trustie2/public/images/footer_logo/buaa_scse.png and /dev/null differ
diff --git a/trustie2/public/images/footer_logo/inforbus.png b/trustie2/public/images/footer_logo/inforbus.png
deleted file mode 100644
index f756b12d2..000000000
Binary files a/trustie2/public/images/footer_logo/inforbus.png and /dev/null differ
diff --git a/trustie2/public/images/footer_logo/iscas.png b/trustie2/public/images/footer_logo/iscas.png
deleted file mode 100644
index 9e1be99e3..000000000
Binary files a/trustie2/public/images/footer_logo/iscas.png and /dev/null differ
diff --git a/trustie2/public/images/footer_logo/nudt.png b/trustie2/public/images/footer_logo/nudt.png
deleted file mode 100644
index 68ff07fe0..000000000
Binary files a/trustie2/public/images/footer_logo/nudt.png and /dev/null differ
diff --git a/trustie2/public/images/footer_logo/peking_eecs.png b/trustie2/public/images/footer_logo/peking_eecs.png
deleted file mode 100644
index 6c7164f08..000000000
Binary files a/trustie2/public/images/footer_logo/peking_eecs.png and /dev/null differ
diff --git a/trustie2/public/images/group.png b/trustie2/public/images/group.png
deleted file mode 100644
index d80eb2606..000000000
Binary files a/trustie2/public/images/group.png and /dev/null differ
diff --git a/trustie2/public/images/help.png b/trustie2/public/images/help.png
deleted file mode 100644
index d533abd3a..000000000
Binary files a/trustie2/public/images/help.png and /dev/null differ
diff --git a/trustie2/public/images/history.png b/trustie2/public/images/history.png
deleted file mode 100644
index 4f2c12846..000000000
Binary files a/trustie2/public/images/history.png and /dev/null differ
diff --git a/trustie2/public/images/home_images/2.png b/trustie2/public/images/home_images/2.png
deleted file mode 100644
index 49b71cff9..000000000
Binary files a/trustie2/public/images/home_images/2.png and /dev/null differ
diff --git a/trustie2/public/images/home_images/3.png b/trustie2/public/images/home_images/3.png
deleted file mode 100644
index 21a2df642..000000000
Binary files a/trustie2/public/images/home_images/3.png and /dev/null differ
diff --git a/trustie2/public/images/home_images/BackGround.gif b/trustie2/public/images/home_images/BackGround.gif
deleted file mode 100644
index 90d70b4b5..000000000
Binary files a/trustie2/public/images/home_images/BackGround.gif and /dev/null differ
diff --git a/trustie2/public/images/home_images/logo1.png b/trustie2/public/images/home_images/logo1.png
deleted file mode 100644
index 57ff0ccf2..000000000
Binary files a/trustie2/public/images/home_images/logo1.png and /dev/null differ
diff --git a/trustie2/public/images/home_new.png b/trustie2/public/images/home_new.png
deleted file mode 100644
index 57ff0ccf2..000000000
Binary files a/trustie2/public/images/home_new.png and /dev/null differ
diff --git a/trustie2/public/images/home_project.png b/trustie2/public/images/home_project.png
deleted file mode 100644
index 21a2df642..000000000
Binary files a/trustie2/public/images/home_project.png and /dev/null differ
diff --git a/trustie2/public/images/home_req.png b/trustie2/public/images/home_req.png
deleted file mode 100644
index 49b71cff9..000000000
Binary files a/trustie2/public/images/home_req.png and /dev/null differ
diff --git a/trustie2/public/images/hourglass.png b/trustie2/public/images/hourglass.png
deleted file mode 100644
index 57b03ce7a..000000000
Binary files a/trustie2/public/images/hourglass.png and /dev/null differ
diff --git a/trustie2/public/images/issue_tag.png b/trustie2/public/images/issue_tag.png
deleted file mode 100644
index eacaf7a54..000000000
Binary files a/trustie2/public/images/issue_tag.png and /dev/null differ
diff --git a/trustie2/public/images/issues-closed.png b/trustie2/public/images/issues-closed.png
deleted file mode 100644
index 167048fef..000000000
Binary files a/trustie2/public/images/issues-closed.png and /dev/null differ
diff --git a/trustie2/public/images/issues.png b/trustie2/public/images/issues.png
deleted file mode 100644
index a934d6cea..000000000
Binary files a/trustie2/public/images/issues.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_bq.png b/trustie2/public/images/jstoolbar/bt_bq.png
deleted file mode 100644
index d56179504..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_bq.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_bq_remove.png b/trustie2/public/images/jstoolbar/bt_bq_remove.png
deleted file mode 100644
index 467957fde..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_bq_remove.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_code.png b/trustie2/public/images/jstoolbar/bt_code.png
deleted file mode 100644
index 0a6e11652..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_code.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_del.png b/trustie2/public/images/jstoolbar/bt_del.png
deleted file mode 100644
index 16bf5fad0..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_del.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_em.png b/trustie2/public/images/jstoolbar/bt_em.png
deleted file mode 100644
index 741c3bf5a..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_em.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_h1.png b/trustie2/public/images/jstoolbar/bt_h1.png
deleted file mode 100644
index 05a1dfd83..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_h1.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_h2.png b/trustie2/public/images/jstoolbar/bt_h2.png
deleted file mode 100644
index d747a5aad..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_h2.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_h3.png b/trustie2/public/images/jstoolbar/bt_h3.png
deleted file mode 100644
index b37d4375b..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_h3.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_img.png b/trustie2/public/images/jstoolbar/bt_img.png
deleted file mode 100644
index 3691d1f1e..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_img.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_ins.png b/trustie2/public/images/jstoolbar/bt_ins.png
deleted file mode 100644
index 1a6683a36..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_ins.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_link.png b/trustie2/public/images/jstoolbar/bt_link.png
deleted file mode 100644
index 74c9e0c51..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_link.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_ol.png b/trustie2/public/images/jstoolbar/bt_ol.png
deleted file mode 100644
index f895ec64d..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_ol.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_pre.png b/trustie2/public/images/jstoolbar/bt_pre.png
deleted file mode 100644
index 8056ddd49..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_pre.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_strong.png b/trustie2/public/images/jstoolbar/bt_strong.png
deleted file mode 100644
index ff338810b..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_strong.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/bt_ul.png b/trustie2/public/images/jstoolbar/bt_ul.png
deleted file mode 100644
index 65c39f0f4..000000000
Binary files a/trustie2/public/images/jstoolbar/bt_ul.png and /dev/null differ
diff --git a/trustie2/public/images/jstoolbar/logo1.png b/trustie2/public/images/jstoolbar/logo1.png
deleted file mode 100644
index 57ff0ccf2..000000000
Binary files a/trustie2/public/images/jstoolbar/logo1.png and /dev/null differ
diff --git a/trustie2/public/images/lightning.png b/trustie2/public/images/lightning.png
deleted file mode 100644
index 81a544fab..000000000
Binary files a/trustie2/public/images/lightning.png and /dev/null differ
diff --git a/trustie2/public/images/link.png b/trustie2/public/images/link.png
deleted file mode 100644
index 53927566a..000000000
Binary files a/trustie2/public/images/link.png and /dev/null differ
diff --git a/trustie2/public/images/link_break.png b/trustie2/public/images/link_break.png
deleted file mode 100644
index 523575306..000000000
Binary files a/trustie2/public/images/link_break.png and /dev/null differ
diff --git a/trustie2/public/images/list-icon.png b/trustie2/public/images/list-icon.png
deleted file mode 100644
index 930d6aae0..000000000
Binary files a/trustie2/public/images/list-icon.png and /dev/null differ
diff --git a/trustie2/public/images/loading.gif b/trustie2/public/images/loading.gif
deleted file mode 100644
index 085ccaeca..000000000
Binary files a/trustie2/public/images/loading.gif and /dev/null differ
diff --git a/trustie2/public/images/locked.png b/trustie2/public/images/locked.png
deleted file mode 100644
index 5c46f15cb..000000000
Binary files a/trustie2/public/images/locked.png and /dev/null differ
diff --git a/trustie2/public/images/logo-only_med.png b/trustie2/public/images/logo-only_med.png
deleted file mode 100644
index fa5df376b..000000000
Binary files a/trustie2/public/images/logo-only_med.png and /dev/null differ
diff --git a/trustie2/public/images/logo.png b/trustie2/public/images/logo.png
deleted file mode 100644
index 9a5bf367d..000000000
Binary files a/trustie2/public/images/logo.png and /dev/null differ
diff --git a/trustie2/public/images/logo2.png b/trustie2/public/images/logo2.png
deleted file mode 100644
index 83b09c3a3..000000000
Binary files a/trustie2/public/images/logo2.png and /dev/null differ
diff --git a/trustie2/public/images/logo3.png b/trustie2/public/images/logo3.png
deleted file mode 100644
index f961569ae..000000000
Binary files a/trustie2/public/images/logo3.png and /dev/null differ
diff --git a/trustie2/public/images/logo4.png b/trustie2/public/images/logo4.png
deleted file mode 100644
index e7a513a9f..000000000
Binary files a/trustie2/public/images/logo4.png and /dev/null differ
diff --git a/trustie2/public/images/logo5.png b/trustie2/public/images/logo5.png
deleted file mode 100644
index c6cb4b756..000000000
Binary files a/trustie2/public/images/logo5.png and /dev/null differ
diff --git a/trustie2/public/images/logo_ent.png b/trustie2/public/images/logo_ent.png
deleted file mode 100644
index 12aaafd0d..000000000
Binary files a/trustie2/public/images/logo_ent.png and /dev/null differ
diff --git a/trustie2/public/images/magnifier.png b/trustie2/public/images/magnifier.png
deleted file mode 100644
index cf3d97f75..000000000
Binary files a/trustie2/public/images/magnifier.png and /dev/null differ
diff --git a/trustie2/public/images/mes.png b/trustie2/public/images/mes.png
deleted file mode 100644
index 34c8f0afd..000000000
Binary files a/trustie2/public/images/mes.png and /dev/null differ
diff --git a/trustie2/public/images/message.png b/trustie2/public/images/message.png
deleted file mode 100644
index 0017800f1..000000000
Binary files a/trustie2/public/images/message.png and /dev/null differ
diff --git a/trustie2/public/images/milestone_done.png b/trustie2/public/images/milestone_done.png
deleted file mode 100644
index 5fdcb415c..000000000
Binary files a/trustie2/public/images/milestone_done.png and /dev/null differ
diff --git a/trustie2/public/images/milestone_late.png b/trustie2/public/images/milestone_late.png
deleted file mode 100644
index cf922e954..000000000
Binary files a/trustie2/public/images/milestone_late.png and /dev/null differ
diff --git a/trustie2/public/images/milestone_todo.png b/trustie2/public/images/milestone_todo.png
deleted file mode 100644
index 4c051c857..000000000
Binary files a/trustie2/public/images/milestone_todo.png and /dev/null differ
diff --git a/trustie2/public/images/move.png b/trustie2/public/images/move.png
deleted file mode 100644
index 7f269c366..000000000
Binary files a/trustie2/public/images/move.png and /dev/null differ
diff --git a/trustie2/public/images/nav_icon.png b/trustie2/public/images/nav_icon.png
deleted file mode 100644
index 1b4e61aec..000000000
Binary files a/trustie2/public/images/nav_icon.png and /dev/null differ
diff --git a/trustie2/public/images/new/fenxiang.png b/trustie2/public/images/new/fenxiang.png
deleted file mode 100644
index cce90bcbe..000000000
Binary files a/trustie2/public/images/new/fenxiang.png and /dev/null differ
diff --git a/trustie2/public/images/new/liuyan.png b/trustie2/public/images/new/liuyan.png
deleted file mode 100644
index 391bbd952..000000000
Binary files a/trustie2/public/images/new/liuyan.png and /dev/null differ
diff --git a/trustie2/public/images/new/liuyan2.png b/trustie2/public/images/new/liuyan2.png
deleted file mode 100644
index ad04944da..000000000
Binary files a/trustie2/public/images/new/liuyan2.png and /dev/null differ
diff --git a/trustie2/public/images/new/logo.gif b/trustie2/public/images/new/logo.gif
deleted file mode 100644
index 6c099118c..000000000
Binary files a/trustie2/public/images/new/logo.gif and /dev/null differ
diff --git a/trustie2/public/images/new/logo.png b/trustie2/public/images/new/logo.png
deleted file mode 100644
index b58caabfa..000000000
Binary files a/trustie2/public/images/new/logo.png and /dev/null differ
diff --git a/trustie2/public/images/new/logo_top.png b/trustie2/public/images/new/logo_top.png
deleted file mode 100644
index 6d933b4b2..000000000
Binary files a/trustie2/public/images/new/logo_top.png and /dev/null differ
diff --git a/trustie2/public/images/new/mlogo.png b/trustie2/public/images/new/mlogo.png
deleted file mode 100644
index cce3b9ccf..000000000
Binary files a/trustie2/public/images/new/mlogo.png and /dev/null differ
diff --git a/trustie2/public/images/new/news.png b/trustie2/public/images/new/news.png
deleted file mode 100644
index 1f0332907..000000000
Binary files a/trustie2/public/images/new/news.png and /dev/null differ
diff --git a/trustie2/public/images/new/small.png b/trustie2/public/images/new/small.png
deleted file mode 100644
index cf2f738cb..000000000
Binary files a/trustie2/public/images/new/small.png and /dev/null differ
diff --git a/trustie2/public/images/new/user.jpg b/trustie2/public/images/new/user.jpg
deleted file mode 100644
index 68a02e4a7..000000000
Binary files a/trustie2/public/images/new/user.jpg and /dev/null differ
diff --git a/trustie2/public/images/new/zhishu.png b/trustie2/public/images/new/zhishu.png
deleted file mode 100644
index e69f10b48..000000000
Binary files a/trustie2/public/images/new/zhishu.png and /dev/null differ
diff --git a/trustie2/public/images/new/zhishu2.png b/trustie2/public/images/new/zhishu2.png
deleted file mode 100644
index 7784e8479..000000000
Binary files a/trustie2/public/images/new/zhishu2.png and /dev/null differ
diff --git a/trustie2/public/images/news.png b/trustie2/public/images/news.png
deleted file mode 100644
index aa857e75b..000000000
Binary files a/trustie2/public/images/news.png and /dev/null differ
diff --git a/trustie2/public/images/openid-bg.gif b/trustie2/public/images/openid-bg.gif
deleted file mode 100644
index e2d8377db..000000000
Binary files a/trustie2/public/images/openid-bg.gif and /dev/null differ
diff --git a/trustie2/public/images/package.png b/trustie2/public/images/package.png
deleted file mode 100644
index c35e832da..000000000
Binary files a/trustie2/public/images/package.png and /dev/null differ
diff --git a/trustie2/public/images/pai.png b/trustie2/public/images/pai.png
deleted file mode 100644
index 98e8ca4c7..000000000
Binary files a/trustie2/public/images/pai.png and /dev/null differ
diff --git a/trustie2/public/images/plugin.png b/trustie2/public/images/plugin.png
deleted file mode 100644
index 5a49f577e..000000000
Binary files a/trustie2/public/images/plugin.png and /dev/null differ
diff --git a/trustie2/public/images/praise.png b/trustie2/public/images/praise.png
deleted file mode 100644
index 808d18134..000000000
Binary files a/trustie2/public/images/praise.png and /dev/null differ
diff --git a/trustie2/public/images/praise_tread/praise_false.png b/trustie2/public/images/praise_tread/praise_false.png
deleted file mode 100644
index 9979427e0..000000000
Binary files a/trustie2/public/images/praise_tread/praise_false.png and /dev/null differ
diff --git a/trustie2/public/images/praise_tread/praise_true.png b/trustie2/public/images/praise_tread/praise_true.png
deleted file mode 100644
index cb78f4839..000000000
Binary files a/trustie2/public/images/praise_tread/praise_true.png and /dev/null differ
diff --git a/trustie2/public/images/praise_tread/tread_false.png b/trustie2/public/images/praise_tread/tread_false.png
deleted file mode 100644
index 884cd380c..000000000
Binary files a/trustie2/public/images/praise_tread/tread_false.png and /dev/null differ
diff --git a/trustie2/public/images/praise_tread/tread_true.png b/trustie2/public/images/praise_tread/tread_true.png
deleted file mode 100644
index b4328a0f5..000000000
Binary files a/trustie2/public/images/praise_tread/tread_true.png and /dev/null differ
diff --git a/trustie2/public/images/project_marker.png b/trustie2/public/images/project_marker.png
deleted file mode 100644
index 4124787d0..000000000
Binary files a/trustie2/public/images/project_marker.png and /dev/null differ
diff --git a/trustie2/public/images/projects.png b/trustie2/public/images/projects.png
deleted file mode 100644
index 018b8b956..000000000
Binary files a/trustie2/public/images/projects.png and /dev/null differ
diff --git a/trustie2/public/images/qrweixin.jpg b/trustie2/public/images/qrweixin.jpg
deleted file mode 100644
index 26555f72c..000000000
Binary files a/trustie2/public/images/qrweixin.jpg and /dev/null differ
diff --git a/trustie2/public/images/reload.png b/trustie2/public/images/reload.png
deleted file mode 100644
index 384147dca..000000000
Binary files a/trustie2/public/images/reload.png and /dev/null differ
diff --git a/trustie2/public/images/report.png b/trustie2/public/images/report.png
deleted file mode 100644
index 4c0f857ca..000000000
Binary files a/trustie2/public/images/report.png and /dev/null differ
diff --git a/trustie2/public/images/requirements/reference.jpg b/trustie2/public/images/requirements/reference.jpg
deleted file mode 100644
index 603bf9b46..000000000
Binary files a/trustie2/public/images/requirements/reference.jpg and /dev/null differ
diff --git a/trustie2/public/images/requirements/req.jpg b/trustie2/public/images/requirements/req.jpg
deleted file mode 100644
index c299b3cb7..000000000
Binary files a/trustie2/public/images/requirements/req.jpg and /dev/null differ
diff --git a/trustie2/public/images/save.png b/trustie2/public/images/save.png
deleted file mode 100644
index 7535814f7..000000000
Binary files a/trustie2/public/images/save.png and /dev/null differ
diff --git a/trustie2/public/images/school/117.gif b/trustie2/public/images/school/117.gif
deleted file mode 100644
index 756872373..000000000
Binary files a/trustie2/public/images/school/117.gif and /dev/null differ
diff --git a/trustie2/public/images/school/default.png b/trustie2/public/images/school/default.png
deleted file mode 100644
index a6475f70d..000000000
Binary files a/trustie2/public/images/school/default.png and /dev/null differ
diff --git a/trustie2/public/images/score.png b/trustie2/public/images/score.png
deleted file mode 100644
index 3fa47462f..000000000
Binary files a/trustie2/public/images/score.png and /dev/null differ
diff --git a/trustie2/public/images/search_bar.png b/trustie2/public/images/search_bar.png
deleted file mode 100644
index 85aa4b740..000000000
Binary files a/trustie2/public/images/search_bar.png and /dev/null differ
diff --git a/trustie2/public/images/seems_rateable/bg_jRatingInfos.png b/trustie2/public/images/seems_rateable/bg_jRatingInfos.png
deleted file mode 100644
index af5bf556e..000000000
Binary files a/trustie2/public/images/seems_rateable/bg_jRatingInfos.png and /dev/null differ
diff --git a/trustie2/public/images/seems_rateable/small.png b/trustie2/public/images/seems_rateable/small.png
deleted file mode 100644
index de1826f59..000000000
Binary files a/trustie2/public/images/seems_rateable/small.png and /dev/null differ
diff --git a/trustie2/public/images/seems_rateable/stars.png b/trustie2/public/images/seems_rateable/stars.png
deleted file mode 100644
index 2df62b026..000000000
Binary files a/trustie2/public/images/seems_rateable/stars.png and /dev/null differ
diff --git a/trustie2/public/images/server_key.png b/trustie2/public/images/server_key.png
deleted file mode 100644
index ecd517425..000000000
Binary files a/trustie2/public/images/server_key.png and /dev/null differ
diff --git a/trustie2/public/images/showmodal/good.png b/trustie2/public/images/showmodal/good.png
deleted file mode 100644
index 9bf7ca7a9..000000000
Binary files a/trustie2/public/images/showmodal/good.png and /dev/null differ
diff --git a/trustie2/public/images/showmodal/hd-bg.png b/trustie2/public/images/showmodal/hd-bg.png
deleted file mode 100644
index cfaa67a6b..000000000
Binary files a/trustie2/public/images/showmodal/hd-bg.png and /dev/null differ
diff --git a/trustie2/public/images/showmodal/modal_close.png b/trustie2/public/images/showmodal/modal_close.png
deleted file mode 100644
index 80655bbcf..000000000
Binary files a/trustie2/public/images/showmodal/modal_close.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/add.png b/trustie2/public/images/sidebar/add.png
deleted file mode 100644
index cd804d090..000000000
Binary files a/trustie2/public/images/sidebar/add.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/add_enterprise.png b/trustie2/public/images/sidebar/add_enterprise.png
deleted file mode 100644
index 0a9ae4abe..000000000
Binary files a/trustie2/public/images/sidebar/add_enterprise.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/female.png b/trustie2/public/images/sidebar/female.png
deleted file mode 100644
index 94d1d7976..000000000
Binary files a/trustie2/public/images/sidebar/female.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/fork.png b/trustie2/public/images/sidebar/fork.png
deleted file mode 100644
index 488391103..000000000
Binary files a/trustie2/public/images/sidebar/fork.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/forums.png b/trustie2/public/images/sidebar/forums.png
deleted file mode 100644
index 9beab407c..000000000
Binary files a/trustie2/public/images/sidebar/forums.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/go.png b/trustie2/public/images/sidebar/go.png
deleted file mode 100644
index 357ae8d8b..000000000
Binary files a/trustie2/public/images/sidebar/go.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/male.png b/trustie2/public/images/sidebar/male.png
deleted file mode 100644
index 294e8d38d..000000000
Binary files a/trustie2/public/images/sidebar/male.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/minus.png b/trustie2/public/images/sidebar/minus.png
deleted file mode 100644
index 3a4c8330f..000000000
Binary files a/trustie2/public/images/sidebar/minus.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/stop.png b/trustie2/public/images/sidebar/stop.png
deleted file mode 100644
index 175eafd0a..000000000
Binary files a/trustie2/public/images/sidebar/stop.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/tag_disagree.png b/trustie2/public/images/sidebar/tag_disagree.png
deleted file mode 100644
index 6c67a8741..000000000
Binary files a/trustie2/public/images/sidebar/tag_disagree.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/tag_title.png b/trustie2/public/images/sidebar/tag_title.png
deleted file mode 100644
index 890d1af0d..000000000
Binary files a/trustie2/public/images/sidebar/tag_title.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/tags.png b/trustie2/public/images/sidebar/tags.png
deleted file mode 100644
index 32d3ea8c4..000000000
Binary files a/trustie2/public/images/sidebar/tags.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/tags_enterprise.png b/trustie2/public/images/sidebar/tags_enterprise.png
deleted file mode 100644
index 9701b19fb..000000000
Binary files a/trustie2/public/images/sidebar/tags_enterprise.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/tool_tag.png b/trustie2/public/images/sidebar/tool_tag.png
deleted file mode 100644
index a991880ec..000000000
Binary files a/trustie2/public/images/sidebar/tool_tag.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/tool_tag2.png b/trustie2/public/images/sidebar/tool_tag2.png
deleted file mode 100644
index 3c14e5ebb..000000000
Binary files a/trustie2/public/images/sidebar/tool_tag2.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/tool_tag_alpha.png b/trustie2/public/images/sidebar/tool_tag_alpha.png
deleted file mode 100644
index 902d19988..000000000
Binary files a/trustie2/public/images/sidebar/tool_tag_alpha.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/tool_tag_enterprise.png b/trustie2/public/images/sidebar/tool_tag_enterprise.png
deleted file mode 100644
index 4dd8b216d..000000000
Binary files a/trustie2/public/images/sidebar/tool_tag_enterprise.png and /dev/null differ
diff --git a/trustie2/public/images/sidebar/watch.png b/trustie2/public/images/sidebar/watch.png
deleted file mode 100644
index b80d63343..000000000
Binary files a/trustie2/public/images/sidebar/watch.png and /dev/null differ
diff --git a/trustie2/public/images/sort_asc.png b/trustie2/public/images/sort_asc.png
deleted file mode 100644
index fbfbcdfa4..000000000
Binary files a/trustie2/public/images/sort_asc.png and /dev/null differ
diff --git a/trustie2/public/images/sort_desc.png b/trustie2/public/images/sort_desc.png
deleted file mode 100644
index 28e977f03..000000000
Binary files a/trustie2/public/images/sort_desc.png and /dev/null differ
diff --git a/trustie2/public/images/stars_ro.png b/trustie2/public/images/stars_ro.png
deleted file mode 100644
index 4c1da3c88..000000000
Binary files a/trustie2/public/images/stars_ro.png and /dev/null differ
diff --git a/trustie2/public/images/statistic_background.png b/trustie2/public/images/statistic_background.png
deleted file mode 100644
index d43966e05..000000000
Binary files a/trustie2/public/images/statistic_background.png and /dev/null differ
diff --git a/trustie2/public/images/stats.png b/trustie2/public/images/stats.png
deleted file mode 100644
index 0b120a49b..000000000
Binary files a/trustie2/public/images/stats.png and /dev/null differ
diff --git a/trustie2/public/images/support.png b/trustie2/public/images/support.png
deleted file mode 100644
index 167048fef..000000000
Binary files a/trustie2/public/images/support.png and /dev/null differ
diff --git a/trustie2/public/images/table_multiple.png b/trustie2/public/images/table_multiple.png
deleted file mode 100644
index 057f4a5e7..000000000
Binary files a/trustie2/public/images/table_multiple.png and /dev/null differ
diff --git a/trustie2/public/images/task.png b/trustie2/public/images/task.png
deleted file mode 100644
index b686c69ef..000000000
Binary files a/trustie2/public/images/task.png and /dev/null differ
diff --git a/trustie2/public/images/task_done.png b/trustie2/public/images/task_done.png
deleted file mode 100644
index 5fdcb415c..000000000
Binary files a/trustie2/public/images/task_done.png and /dev/null differ
diff --git a/trustie2/public/images/task_late.png b/trustie2/public/images/task_late.png
deleted file mode 100644
index 71fd2d70b..000000000
Binary files a/trustie2/public/images/task_late.png and /dev/null differ
diff --git a/trustie2/public/images/task_parent_end.png b/trustie2/public/images/task_parent_end.png
deleted file mode 100644
index 9442b86a5..000000000
Binary files a/trustie2/public/images/task_parent_end.png and /dev/null differ
diff --git a/trustie2/public/images/task_todo.png b/trustie2/public/images/task_todo.png
deleted file mode 100644
index 632406ee1..000000000
Binary files a/trustie2/public/images/task_todo.png and /dev/null differ
diff --git a/trustie2/public/images/text_list_bullets.png b/trustie2/public/images/text_list_bullets.png
deleted file mode 100644
index 008820722..000000000
Binary files a/trustie2/public/images/text_list_bullets.png and /dev/null differ
diff --git a/trustie2/public/images/textfield.png b/trustie2/public/images/textfield.png
deleted file mode 100644
index 408c6b027..000000000
Binary files a/trustie2/public/images/textfield.png and /dev/null differ
diff --git a/trustie2/public/images/textfield_key.png b/trustie2/public/images/textfield_key.png
deleted file mode 100644
index a9d5e4f8c..000000000
Binary files a/trustie2/public/images/textfield_key.png and /dev/null differ
diff --git a/trustie2/public/images/ticket.png b/trustie2/public/images/ticket.png
deleted file mode 100644
index 73756ed47..000000000
Binary files a/trustie2/public/images/ticket.png and /dev/null differ
diff --git a/trustie2/public/images/ticket_checked.png b/trustie2/public/images/ticket_checked.png
deleted file mode 100644
index fc25958ac..000000000
Binary files a/trustie2/public/images/ticket_checked.png and /dev/null differ
diff --git a/trustie2/public/images/ticket_edit.png b/trustie2/public/images/ticket_edit.png
deleted file mode 100644
index 89df6cba8..000000000
Binary files a/trustie2/public/images/ticket_edit.png and /dev/null differ
diff --git a/trustie2/public/images/ticket_go.png b/trustie2/public/images/ticket_go.png
deleted file mode 100644
index 2aaec3813..000000000
Binary files a/trustie2/public/images/ticket_go.png and /dev/null differ
diff --git a/trustie2/public/images/ticket_note.png b/trustie2/public/images/ticket_note.png
deleted file mode 100644
index c8de16573..000000000
Binary files a/trustie2/public/images/ticket_note.png and /dev/null differ
diff --git a/trustie2/public/images/time.png b/trustie2/public/images/time.png
deleted file mode 100644
index fa1bf5f96..000000000
Binary files a/trustie2/public/images/time.png and /dev/null differ
diff --git a/trustie2/public/images/time_add.png b/trustie2/public/images/time_add.png
deleted file mode 100644
index 70119f77a..000000000
Binary files a/trustie2/public/images/time_add.png and /dev/null differ
diff --git a/trustie2/public/images/time_member.png b/trustie2/public/images/time_member.png
deleted file mode 100644
index 81f91726d..000000000
Binary files a/trustie2/public/images/time_member.png and /dev/null differ
diff --git a/trustie2/public/images/toggle_check.png b/trustie2/public/images/toggle_check.png
deleted file mode 100644
index da85f26df..000000000
Binary files a/trustie2/public/images/toggle_check.png and /dev/null differ
diff --git a/trustie2/public/images/transparent.png b/trustie2/public/images/transparent.png
deleted file mode 100644
index 7fc28b5e2..000000000
Binary files a/trustie2/public/images/transparent.png and /dev/null differ
diff --git a/trustie2/public/images/tread.png b/trustie2/public/images/tread.png
deleted file mode 100644
index a843cc3dc..000000000
Binary files a/trustie2/public/images/tread.png and /dev/null differ
diff --git a/trustie2/public/images/true.png b/trustie2/public/images/true.png
deleted file mode 100644
index a2ed1a378..000000000
Binary files a/trustie2/public/images/true.png and /dev/null differ
diff --git a/trustie2/public/images/twurn.com_.png b/trustie2/public/images/twurn.com_.png
deleted file mode 100644
index 8e7c6d120..000000000
Binary files a/trustie2/public/images/twurn.com_.png and /dev/null differ
diff --git a/trustie2/public/images/unlock.png b/trustie2/public/images/unlock.png
deleted file mode 100644
index 0c284d992..000000000
Binary files a/trustie2/public/images/unlock.png and /dev/null differ
diff --git a/trustie2/public/images/up_hand.png b/trustie2/public/images/up_hand.png
deleted file mode 100644
index cf6980a6d..000000000
Binary files a/trustie2/public/images/up_hand.png and /dev/null differ
diff --git a/trustie2/public/images/up_hand_after_click.png b/trustie2/public/images/up_hand_after_click.png
deleted file mode 100644
index f5d49de1d..000000000
Binary files a/trustie2/public/images/up_hand_after_click.png and /dev/null differ
diff --git a/trustie2/public/images/upgrading.jpg b/trustie2/public/images/upgrading.jpg
deleted file mode 100644
index 2e6372192..000000000
Binary files a/trustie2/public/images/upgrading.jpg and /dev/null differ
diff --git a/trustie2/public/images/user.png b/trustie2/public/images/user.png
deleted file mode 100644
index 264381ed2..000000000
Binary files a/trustie2/public/images/user.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/L1.png b/trustie2/public/images/user_images/L1.png
deleted file mode 100644
index 178f783f0..000000000
Binary files a/trustie2/public/images/user_images/L1.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/L2.png b/trustie2/public/images/user_images/L2.png
deleted file mode 100644
index 6b816f8fa..000000000
Binary files a/trustie2/public/images/user_images/L2.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/L3.png b/trustie2/public/images/user_images/L3.png
deleted file mode 100644
index 6cf2afb17..000000000
Binary files a/trustie2/public/images/user_images/L3.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/fans.png b/trustie2/public/images/user_images/fans.png
deleted file mode 100644
index 3e48100df..000000000
Binary files a/trustie2/public/images/user_images/fans.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/fork.png b/trustie2/public/images/user_images/fork.png
deleted file mode 100644
index 488391103..000000000
Binary files a/trustie2/public/images/user_images/fork.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/in_share.png b/trustie2/public/images/user_images/in_share.png
deleted file mode 100644
index 77aecfd8a..000000000
Binary files a/trustie2/public/images/user_images/in_share.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/iuser.png b/trustie2/public/images/user_images/iuser.png
deleted file mode 100644
index 6cb78eba2..000000000
Binary files a/trustie2/public/images/user_images/iuser.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/m1.png b/trustie2/public/images/user_images/m1.png
deleted file mode 100644
index 40fc59c6c..000000000
Binary files a/trustie2/public/images/user_images/m1.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/m2.png b/trustie2/public/images/user_images/m2.png
deleted file mode 100644
index f00bf665b..000000000
Binary files a/trustie2/public/images/user_images/m2.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/me.jpg b/trustie2/public/images/user_images/me.jpg
deleted file mode 100644
index f4f76491a..000000000
Binary files a/trustie2/public/images/user_images/me.jpg and /dev/null differ
diff --git a/trustie2/public/images/user_images/mlogo.png b/trustie2/public/images/user_images/mlogo.png
deleted file mode 100644
index cce3b9ccf..000000000
Binary files a/trustie2/public/images/user_images/mlogo.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/project.jpg b/trustie2/public/images/user_images/project.jpg
deleted file mode 100644
index 576239c06..000000000
Binary files a/trustie2/public/images/user_images/project.jpg and /dev/null differ
diff --git a/trustie2/public/images/user_images/project.png b/trustie2/public/images/user_images/project.png
deleted file mode 100644
index 82ce8f6a7..000000000
Binary files a/trustie2/public/images/user_images/project.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/share.png b/trustie2/public/images/user_images/share.png
deleted file mode 100644
index 108425b2f..000000000
Binary files a/trustie2/public/images/user_images/share.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/user2.png b/trustie2/public/images/user_images/user2.png
deleted file mode 100644
index b0fe8ad82..000000000
Binary files a/trustie2/public/images/user_images/user2.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/watch.png b/trustie2/public/images/user_images/watch.png
deleted file mode 100644
index b80d63343..000000000
Binary files a/trustie2/public/images/user_images/watch.png and /dev/null differ
diff --git a/trustie2/public/images/user_images/watchers.png b/trustie2/public/images/user_images/watchers.png
deleted file mode 100644
index 7e057a202..000000000
Binary files a/trustie2/public/images/user_images/watchers.png and /dev/null differ
diff --git a/trustie2/public/images/version_marker.png b/trustie2/public/images/version_marker.png
deleted file mode 100644
index 0368ca290..000000000
Binary files a/trustie2/public/images/version_marker.png and /dev/null differ
diff --git a/trustie2/public/images/warning.png b/trustie2/public/images/warning.png
deleted file mode 100644
index c5e482f84..000000000
Binary files a/trustie2/public/images/warning.png and /dev/null differ
diff --git a/trustie2/public/images/watcher/watcher_button.png b/trustie2/public/images/watcher/watcher_button.png
deleted file mode 100644
index 2029d2f52..000000000
Binary files a/trustie2/public/images/watcher/watcher_button.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/1.png b/trustie2/public/images/welcome/1.png
deleted file mode 100644
index 2adb6279e..000000000
Binary files a/trustie2/public/images/welcome/1.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/2.png b/trustie2/public/images/welcome/2.png
deleted file mode 100644
index 714281792..000000000
Binary files a/trustie2/public/images/welcome/2.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/3.png b/trustie2/public/images/welcome/3.png
deleted file mode 100644
index 76e02b422..000000000
Binary files a/trustie2/public/images/welcome/3.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/4.png b/trustie2/public/images/welcome/4.png
deleted file mode 100644
index da95636ee..000000000
Binary files a/trustie2/public/images/welcome/4.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/background.png b/trustie2/public/images/welcome/background.png
deleted file mode 100644
index d7dc8d40e..000000000
Binary files a/trustie2/public/images/welcome/background.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/background2.png b/trustie2/public/images/welcome/background2.png
deleted file mode 100644
index 6f86c76df..000000000
Binary files a/trustie2/public/images/welcome/background2.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/background3.png b/trustie2/public/images/welcome/background3.png
deleted file mode 100644
index 7d55349ab..000000000
Binary files a/trustie2/public/images/welcome/background3.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/backgroundnew.png b/trustie2/public/images/welcome/backgroundnew.png
deleted file mode 100644
index a61e59b63..000000000
Binary files a/trustie2/public/images/welcome/backgroundnew.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/boards.png b/trustie2/public/images/welcome/boards.png
deleted file mode 100644
index e8bb40e8f..000000000
Binary files a/trustie2/public/images/welcome/boards.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/discuss.png b/trustie2/public/images/welcome/discuss.png
deleted file mode 100644
index 345f48d06..000000000
Binary files a/trustie2/public/images/welcome/discuss.png and /dev/null differ
diff --git a/trustie2/public/images/welcome/news.png b/trustie2/public/images/welcome/news.png
deleted file mode 100644
index 5ea4aa04f..000000000
Binary files a/trustie2/public/images/welcome/news.png and /dev/null differ
diff --git a/trustie2/public/images/wiki_edit.png b/trustie2/public/images/wiki_edit.png
deleted file mode 100644
index e00618a55..000000000
Binary files a/trustie2/public/images/wiki_edit.png and /dev/null differ
diff --git a/trustie2/public/images/zding.gif b/trustie2/public/images/zding.gif
deleted file mode 100644
index 935adfc71..000000000
Binary files a/trustie2/public/images/zding.gif and /dev/null differ
diff --git a/trustie2/public/images/zoom_in.png b/trustie2/public/images/zoom_in.png
deleted file mode 100644
index af4fe0747..000000000
Binary files a/trustie2/public/images/zoom_in.png and /dev/null differ
diff --git a/trustie2/public/images/zoom_out.png b/trustie2/public/images/zoom_out.png
deleted file mode 100644
index 81f28199a..000000000
Binary files a/trustie2/public/images/zoom_out.png and /dev/null differ
diff --git a/trustie2/public/javascripts/application.js b/trustie2/public/javascripts/application.js
deleted file mode 100644
index 81160fa93..000000000
--- a/trustie2/public/javascripts/application.js
+++ /dev/null
@@ -1,624 +0,0 @@
-//= require_directory ./rateable
-/* Redmine - project management software
- Copyright (C) 2006-2013 Jean-Philippe Lang */
-
-function cleanArray (actual){
- var newArray = new Array();
- for (var i = 0; i< actual.length; i++){
- if (actual[i]){
- newArray.push(actual[i]);
- }
- }
- return newArray;
-}
-
-function checkAll(id, checked) {
- if (checked) {
- $('#'+id).find('input[type=checkbox]').attr('checked', true);
- } else {
- $('#'+id).find('input[type=checkbox]').removeAttr('checked');
- }
-}
-
-function toggleCheckboxesBySelector(selector) {
- var all_checked = true;
- $(selector).each(function(index) {
- if (!$(this).is(':checked')) { all_checked = false; }
- });
- $(selector).attr('checked', !all_checked);
-}
-
-function showAndScrollTo(id, focus) {
- $('#'+id).show();
- if (focus !== null) {
- $('#'+focus).focus();
- }
- $('html, body').animate({scrollTop: $('#'+id).offset().top}, 400);
-}
-
-function toggleRowGroup(el) {
- var tr = $(el).parents('tr').first();
- var n = tr.next();
- tr.toggleClass('open');
- while (n.length && !n.hasClass('group')) {
- n.toggle();
- n = n.next('tr');
- }
-}
-
-function collapseAllRowGroups(el) {
- var tbody = $(el).parents('tbody').first();
- tbody.children('tr').each(function(index) {
- if ($(this).hasClass('group')) {
- $(this).removeClass('open');
- } else {
- $(this).hide();
- }
- });
-}
-
-function expandAllRowGroups(el) {
- var tbody = $(el).parents('tbody').first();
- tbody.children('tr').each(function(index) {
- if ($(this).hasClass('group')) {
- $(this).addClass('open');
- } else {
- $(this).show();
- }
- });
-}
-
-function toggleAllRowGroups(el) {
- var tr = $(el).parents('tr').first();
- if (tr.hasClass('open')) {
- collapseAllRowGroups(el);
- } else {
- expandAllRowGroups(el);
- }
-}
-
-function toggleFieldset(el) {
- var fieldset = $(el).parents('fieldset').first();
- fieldset.toggleClass('collapsed');
- fieldset.children('div').toggle();
-}
-
-function hideFieldset(el) {
- var fieldset = $(el).parents('fieldset').first();
- fieldset.toggleClass('collapsed');
- fieldset.children('div').hide();
-}
-
-function initFilters(){
- $('#add_filter_select').change(function(){
- addFilter($(this).val(), '', []);
- });
- $('#filters-table td.field input[type=checkbox]').each(function(){
- toggleFilter($(this).val());
- });
- $('#filters-table td.field input[type=checkbox]').live('click',function(){
- toggleFilter($(this).val());
- });
- $('#filters-table .toggle-multiselect').live('click',function(){
- toggleMultiSelect($(this).siblings('select'));
- });
- $('#filters-table input[type=text]').live('keypress', function(e){
- if (e.keyCode == 13) submit_query_form("query_form");
- });
-}
-
-function addFilter(field, operator, values) {
- var fieldId = field.replace('.', '_');
- var tr = $('#tr_'+fieldId);
- if (tr.length > 0) {
- tr.show();
- } else {
- buildFilterRow(field, operator, values);
- }
- $('#cb_'+fieldId).attr('checked', true);
- toggleFilter(field);
- $('#add_filter_select').val('').children('option').each(function(){
- if ($(this).attr('value') == field) {
- $(this).attr('disabled', true);
- }
- });
-}
-
-function buildFilterRow(field, operator, values) {
- var fieldId = field.replace('.', '_');
- var filterTable = $("#filters-table");
- var filterOptions = availableFilters[field];
- var operators = operatorByType[filterOptions['type']];
- var filterValues = filterOptions['values'];
- var i, select;
-
- var tr = $('').attr('id', 'tr_'+fieldId).html(
- ' ' +
- ' ' +
- ' '
- );
- filterTable.append(tr);
-
- select = tr.find('td.operator select');
- for (i=0;i').val(operators[i]).text(operatorLabels[operators[i]]);
- if (operators[i] == operator) { option.attr('selected', true); }
- select.append(option);
- }
- select.change(function(){ toggleOperator(field); });
-
- switch (filterOptions['type']){
- case "list":
- case "list_optional":
- case "list_status":
- case "list_subprojects":
- tr.find('td.values').append(
- ''
- );
- select = tr.find('td.values select');
- if (values.length > 1) { select.attr('multiple', true); }
- for (i=0;i');
- if ($.isArray(filterValue)) {
- option.val(filterValue[1]).text(filterValue[0]);
- if ($.inArray(filterValue[1], values) > -1) {option.attr('selected', true);}
- } else {
- option.val(filterValue).text(filterValue);
- if ($.inArray(filterValue, values) > -1) {option.attr('selected', true);}
- }
- select.append(option);
- }
- break;
- case "date":
- case "date_past":
- tr.find('td.values').append(
- '' +
- ' ' +
- ' '
- );
- $('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions);
- $('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions);
- $('#values_'+fieldId).val(values[0]);
- break;
- case "string":
- case "text":
- tr.find('td.values').append(
- ''
- );
- $('#values_'+fieldId).val(values[0]);
- break;
- case "relation":
- tr.find('td.values').append(
- '' +
- ''
- );
- $('#values_'+fieldId).val(values[0]);
- select = tr.find('td.values select');
- for (i=0;i');
- option.val(filterValue[1]).text(filterValue[0]);
- if (values[0] == filterValue[1]) { option.attr('selected', true); }
- select.append(option);
- }
- case "integer":
- case "float":
- tr.find('td.values').append(
- '' +
- ' '
- );
- $('#values_'+fieldId+'_1').val(values[0]);
- $('#values_'+fieldId+'_2').val(values[1]);
- break;
- }
-}
-
-function toggleFilter(field) {
- var fieldId = field.replace('.', '_');
- if ($('#cb_' + fieldId).is(':checked')) {
- $("#operators_" + fieldId).show().removeAttr('disabled');
- toggleOperator(field);
- } else {
- $("#operators_" + fieldId).hide().attr('disabled', true);
- enableValues(field, []);
- }
-}
-
-function enableValues(field, indexes) {
- var fieldId = field.replace('.', '_');
- $('#tr_'+fieldId+' td.values .value').each(function(index) {
- if ($.inArray(index, indexes) >= 0) {
- $(this).removeAttr('disabled');
- $(this).parents('span').first().show();
- } else {
- $(this).val('');
- $(this).attr('disabled', true);
- $(this).parents('span').first().hide();
- }
-
- if ($(this).hasClass('group')) {
- $(this).addClass('open');
- } else {
- $(this).show();
- }
- });
-}
-
-function toggleOperator(field) {
- var fieldId = field.replace('.', '_');
- var operator = $("#operators_" + fieldId);
- switch (operator.val()) {
- case "!*":
- case "*":
- case "t":
- case "ld":
- case "w":
- case "lw":
- case "l2w":
- case "m":
- case "lm":
- case "y":
- case "o":
- case "c":
- enableValues(field, []);
- break;
- case "><":
- enableValues(field, [0,1]);
- break;
- case "t+":
- case ">t-":
- case "0) {
- lis.eq(i-1).show();
- }
-}
-
-function displayTabsButtons() {
- var lis;
- var tabsWidth = 0;
- var el;
- $('div.tabs').each(function() {
- el = $(this);
- lis = el.find('ul').children();
- lis.each(function(){
- if ($(this).is(':visible')) {
- tabsWidth += $(this).width() + 6;
- }
- });
- if ((tabsWidth < el.width() - 60) && (lis.first().is(':visible'))) {
- el.find('div.tabs-buttons').hide();
- } else {
- el.find('div.tabs-buttons').show();
- }
- });
-}
-
-function setPredecessorFieldsVisibility() {
- var relationType = $('#relation_relation_type');
- if (relationType.val() == "precedes" || relationType.val() == "follows") {
- $('#predecessor_fields').show();
- } else {
- $('#predecessor_fields').hide();
- }
-}
-
-function showModal(id, width) {
- var el = $('#'+id).first();
- if (el.length === 0 || el.is(':visible')) {return;}
- var title = el.find('h3.title').text();
- el.dialog({
- width: width,
- modal: true,
- resizable: false,
- dialogClass: 'modal',
- title: title
- });
- el.find("input[type=text], input[type=submit]").first().focus();
-}
-
-function hideModal(el) {
- var modal;
- if (el) {
- modal = $(el).parents('.ui-dialog-content');
- } else {
- modal = $('#ajax-modal');
- }
- modal.dialog("close");
-}
-
-function submitPreview(url, form, target) {
- $.ajax({
- url: url,
- type: 'post',
- data: $('#'+form).serialize(),
- success: function(data){
- $('#'+target).html(data);
- }
- });
-}
-
-function collapseScmEntry(id) {
- $('.'+id).each(function() {
- if ($(this).hasClass('open')) {
- collapseScmEntry($(this).attr('id'));
- }
- $(this).hide();
- });
- $('#'+id).removeClass('open');
-}
-
-function expandScmEntry(id) {
- $('.'+id).each(function() {
- $(this).show();
- if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) {
- expandScmEntry($(this).attr('id'));
- }
- });
- $('#'+id).addClass('open');
-}
-
-function scmEntryClick(id, url) {
- el = $('#'+id);
- if (el.hasClass('open')) {
- collapseScmEntry(id);
- el.addClass('collapsed');
- return false;
- } else if (el.hasClass('loaded')) {
- expandScmEntry(id);
- el.removeClass('collapsed');
- return false;
- }
- if (el.hasClass('loading')) {
- return false;
- }
- el.addClass('loading');
- $.ajax({
- url: url,
- success: function(data){
- el.after(data);
- el.addClass('open').addClass('loaded').removeClass('loading');
- }
- });
- return true;
-}
-
-function randomKey(size) {
- var chars = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');
- var key = '';
- for (i = 0; i < size; i++) {
- key += chars[Math.floor(Math.random() * chars.length)];
- }
- return key;
-}
-
-// Can't use Rails' remote select because we need the form data
-function updateIssueFrom(url) {
- $.ajax({
- url: url,
- type: 'post',
- data: $('#issue-form').serialize()
- });
-}
-
-function updateBulkEditFrom(url) {
- $.ajax({
- url: url,
- type: 'post',
- data: $('#bulk_edit_form').serialize()
- });
-}
-
-function clearMessage(id) {
- $('#'+id).val("");
-}
-
-
-function observeAutocompleteField(fieldId, url, options) {
- $(document).ready(function() {
- $('#'+fieldId).autocomplete($.extend({
- source: url,
- select: function(e,ui){self.location="/issues/"+ui.item.value;},
- minLength: 2,
- search: function(){$('#'+fieldId).addClass('ajax-loading');},
- response: function(){$('#'+fieldId).removeClass('ajax-loading');
- }
- }, options));
- $('#'+fieldId).addClass('autocomplete');
-
- });
-
-}
-
-function observeSearchfield(fieldId, targetId, url) {
- $('#'+fieldId).each(function() {
- var $this = $(this);
- $this.addClass('autocomplete');
- $this.attr('data-value-was', $this.val());
- var check = function() {
- var val = $this.val();
- if ($this.attr('data-value-was') != val){
- $this.attr('data-value-was', val);
- $.ajax({
- url: url,
- type: 'get',
- data: {q: $this.val()},
- success: function(data){ if(targetId) $('#'+targetId).html(data); },
- beforeSend: function(){ $this.addClass('ajax-loading'); },
- complete: function(){ $this.removeClass('ajax-loading'); }
- });
- }
- };
- var reset = function() {
- if (timer) {
- clearInterval(timer);
- timer = setInterval(check, 300);
- }
- };
- var timer = setInterval(check, 300);
- $this.bind('keyup click mousemove', reset);
- });
-}
-
-function observeProjectModules() {
- var f = function() {
- /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */
- if ($('#project_enabled_module_names_issue_tracking').attr('checked')) {
- $('#project_trackers').show();
- }else{
- $('#project_trackers').hide();
- }
- };
-
- $(window).load(f);
- $('#project_enabled_module_names_issue_tracking').change(f);
-}
-
-function initMyPageSortable(list, url) {
- $('#list-'+list).sortable({
- connectWith: '.block-receiver',
- tolerance: 'pointer',
- update: function(){
- $.ajax({
- url: url,
- type: 'post',
- data: {'blocks': $.map($('#list-'+list).children(), function(el){return $(el).attr('id');})}
- });
- }
- });
- $("#list-top, #list-left, #list-right").disableSelection();
-}
-
-var warnLeavingUnsavedMessage;
-function warnLeavingUnsaved(message) {
- warnLeavingUnsavedMessage = message;
-
- $('form').submit(function(){
- $('textarea').removeData('changed');
- });
- $('textarea').change(function(){
- $(this).data('changed', 'changed');
- });
- window.onbeforeunload = function(){
- var warn = false;
- $('textarea').blur().each(function(){
- if ($(this).data('changed')) {
- warn = true;
- }
- });
- if (warn) {return warnLeavingUnsavedMessage;}
- };
-}
-
-function setupAjaxIndicator() {
-
- $('#ajax-indicator').bind('ajaxSend', function(event, xhr, settings) {
-
- if ($('.ajax-loading').length === 0 && settings.contentType != 'application/octet-stream') {
- $('#ajax-indicator').show();
- }
- });
-
- $('#ajax-indicator').bind('ajaxStop', function() {
- $('#ajax-indicator').hide();
- });
-}
-
-function hideOnLoad() {
- $('.hol').hide();
-}
-
-function addFormObserversForDoubleSubmit() {
- $('form[method=post]').each(function() {
- if (!$(this).hasClass('multiple-submit')) {
- $(this).submit(function(form_submission) {
- if ($(form_submission.target).attr('data-submitted')) {
- form_submission.preventDefault();
- } else {
- $(form_submission.target).attr('data-submitted', true);
- }
- });
- }
- });
-}
-
-function blockEventPropagation(event) {
- event.stopPropagation();
- event.preventDefault();
-}
-
-function toggleAndSettingWordsVal(parent_widget, text_widget, value){
- text_widget.val(value)
- parent_widget.slideToggle(400)
-}
-function transpotUrl (scope) {
- $(scope).each(function(){
- var tmpContent = $(this).html();
- tmpContent = tmpContent.replace(/(^|[^\"\'])(http|ftp|mms|rstp|news|https)(\:\/\/[^<\s\+,,]+)/gi,"$1$2$3<\/a>");
- // tmpContent = tmpContent.replace(/(^|[^\/])(www\.[^<\s\+,,]+)/gi,"$1$2");
- $(this).html(tmpContent);
- });
-}
-
-$(document).ready(setupAjaxIndicator);
-$(document).ready(hideOnLoad);
-$(document).ready(addFormObserversForDoubleSubmit);
-
diff --git a/trustie2/public/javascripts/attachments.js b/trustie2/public/javascripts/attachments.js
deleted file mode 100644
index b487e5472..000000000
--- a/trustie2/public/javascripts/attachments.js
+++ /dev/null
@@ -1,229 +0,0 @@
-/* Redmine - project management software
- Copyright (C) 2006-2013 Jean-Philippe Lang */
-
-function postUpMsg(attachmentId) {
- $.ajax({
- url: '/attachments/renderTag',
- type: "GET",
- data: {
- attachmentId: attachmentId
- }
-
- })
-}
-function addFile(inputEl, file, eagerUpload) {
-
- if ($('#attachments_fields').children().length < 10) {
-
- var attachmentId = addFile.nextAttachmentId++;
-
- var fileSpan = $('', { 'id': 'attachments_' + attachmentId, 'class': 'attachment' });
-
- fileSpan.append(
- $('', { 'type': 'text', 'class': 'filename readonly', 'name': 'attachments[' + attachmentId + '][filename]', 'readonly': 'readonly'}).val(file.name),
- $('', { 'type': 'text', 'class': 'description', 'name': 'attachments[' + attachmentId + '][description]', 'maxlength': 255, 'placeholder': $(inputEl).data('description-placeholder') }).toggle(!eagerUpload),
- $(' ').attr({ 'href': "#", 'class': 'remove-upload', 'data-confirm': "您确定要删除吗?" }).click(removeFile).toggle(!eagerUpload),
- $('', { 'class': 'div_attachments', 'name': 'div_' + 'attachments_' + attachmentId})
- ).appendTo('#attachments_fields');
-
- if (eagerUpload) {
- ajaxUpload(file, attachmentId, fileSpan, inputEl);
-
- }
- return attachmentId;
- }
- return null;
-}
-
-addFile.nextAttachmentId = 1;
-
-function ajaxUpload(file, attachmentId, fileSpan, inputEl) {
-
- function onLoadstart(e) {
- fileSpan.removeClass('ajax-waiting');
- fileSpan.addClass('ajax-loading');
- $('input:submit', $(this).parents('form')).attr('disabled', 'disabled');
- }
-
- function onProgress(e) {
- if (e.lengthComputable) {
- this.progressbar('value', e.loaded * 100 / e.total);
- }
- }
-
- function actualUpload(file, attachmentId, fileSpan, inputEl) {
-
- ajaxUpload.uploading++;
-
- uploadBlob(file, $(inputEl).data('upload-path'), attachmentId, {
- loadstartEventHandler: onLoadstart.bind(progressSpan),
- progressEventHandler: onProgress.bind(progressSpan)
- })
- .done(function (result) {
- progressSpan.progressbar('value', 100).remove();
- fileSpan.find('input.description, a').css('display', 'inline-block');
- })
- .fail(function (result) {
- progressSpan.text(result.statusText);
- }).always(function () {
- ajaxUpload.uploading--;
- fileSpan.removeClass('ajax-loading');
- var form = fileSpan.parents('form');
- if (form.queue('upload').length == 0 && ajaxUpload.uploading == 0) {
- $('input:submit', form).removeAttr('disabled');
- }
- form.dequeue('upload');
- });
-
- //gcm files count and add delete_all link
-
- var count = $('#attachments_fields>span').length;
- $('#upload_file_count').html("已上传" + "" + count + "" + "个文件");
-
- if (count >= 1) {
- var add_attachs = $('.add_attachment');
- var delete_all = $('.remove_all');
- if (delete_all.length < 1) {
- add_attachs.append($(" ").attr({"href": "javascript:void(0)", 'class': 'remove_all', "onclick": "removeAll()"}));
- }
- }
-
- //gcm
-
- }
-
- var progressSpan = $('').insertAfter(fileSpan.find('input.filename'));
- progressSpan.progressbar();
- fileSpan.addClass('ajax-waiting');
-
- var maxSyncUpload = $(inputEl).data('max-concurrent-uploads');
-
- if (maxSyncUpload == null || maxSyncUpload <= 0 || ajaxUpload.uploading < maxSyncUpload)
- actualUpload(file, attachmentId, fileSpan, inputEl);
- else
- $(inputEl).parents('form').queue('upload', actualUpload.bind(this, file, attachmentId, fileSpan, inputEl));
-}
-
-ajaxUpload.uploading = 0;
-
-function removeFile() {
- $(this).parent('span').remove();
- return false;
-}
-
-//gcm delete all file
-function removeAll() {
- if (confirm("您确定要删除所有文件吗?")) {
- $(".remove-upload").removeAttr("data-confirm");
- $(".remove-upload").click();
- }
-// return false;
-}
-//gcm
-
-function uploadBlob(blob, uploadUrl, attachmentId, options) {
-
- var actualOptions = $.extend({
- loadstartEventHandler: $.noop,
- progressEventHandler: $.noop
- }, options);
-
- uploadUrl = uploadUrl + '?attachment_id=' + attachmentId;
- if (blob instanceof window.File) {
- uploadUrl += '&filename=' + encodeURIComponent(blob.name);
- }
-
- return $.ajax(uploadUrl, {
- type: 'POST',
- contentType: 'application/octet-stream',
- beforeSend: function (jqXhr) {
- jqXhr.setRequestHeader('Accept', 'application/js');
- },
- xhr: function () {
- var xhr = $.ajaxSettings.xhr();
- xhr.upload.onloadstart = actualOptions.loadstartEventHandler;
- xhr.upload.onprogress = actualOptions.progressEventHandler;
- return xhr;
- },
- data: blob,
- cache: false,
- processData: false
- });
-}
-
-function addInputFiles(inputEl) {
- var clearedFileInput = $(inputEl).clone().val('');
-
- if (inputEl.files) {
- // upload files using ajax
- uploadAndAttachFiles(inputEl.files, inputEl);
- $(inputEl).remove();
- } else {
- // browser not supporting the file API, upload on form submission
- var attachmentId;
- var aFilename = inputEl.value.split(/\/|\\/);
- attachmentId = addFile(inputEl, { name: aFilename[ aFilename.length - 1 ] }, false);
- if (attachmentId) {
- $(inputEl).attr({ name: 'attachments[' + attachmentId + '][file]', style: 'display:none;' }).appendTo('#attachments_' + attachmentId);
- }
- }
-
- clearedFileInput.insertAfter('#attachments_fields');
-}
-
-function uploadAndAttachFiles(files, inputEl) {
-
- var maxFileSize = $(inputEl).data('max-file-size');
- var maxFileSizeExceeded = $(inputEl).data('max-file-size-message');
-
- var sizeExceeded = false;
- $.each(files, function () {
- if (this.size && maxFileSize != null && this.size > parseInt(maxFileSize)) {
- sizeExceeded = true;
- }
- });
- if (sizeExceeded) {
- window.alert(maxFileSizeExceeded);
- } else {
- $.each(files, function () {
- addFile(inputEl, this, true);
- });
- }
-}
-
-function handleFileDropEvent(e) {
-
- $(this).removeClass('fileover');
- blockEventPropagation(e);
-
- if ($.inArray('Files', e.dataTransfer.types) > -1) {
- uploadAndAttachFiles(e.dataTransfer.files, $('input:file.file_selector'));
- }
-}
-
-function dragOverHandler(e) {
- $(this).addClass('fileover');
- blockEventPropagation(e);
-}
-
-function dragOutHandler(e) {
- $(this).removeClass('fileover');
- blockEventPropagation(e);
-}
-
-function setupFileDrop() {
- if (window.File && window.FileList && window.ProgressEvent && window.FormData) {
-
- $.event.fixHooks.drop = { props: [ 'dataTransfer' ] };
-
- $('form div.box').has('input:file').each(function () {
- $(this).on({
- dragover: dragOverHandler,
- dragleave: dragOutHandler,
- drop: handleFileDropEvent
- });
- });
- }
-}
-
-$(document).ready(setupFileDrop);
diff --git a/trustie2/public/javascripts/avatars.js b/trustie2/public/javascripts/avatars.js
deleted file mode 100644
index 24bc1ee1c..000000000
--- a/trustie2/public/javascripts/avatars.js
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Redmine - project management software
- Copyright (C) 2006-2013 Jean-Philippe Lang
- Modified by Jianfeng Tao, to upload one avatar for user*/
-
-function addFile(inputEl, file, eagerUpload) {
-
- var fileSpan = $('#avatar_file');
-
- //fileSpan.append(
- // $('', { type: 'text', 'class': 'filename readonly', name: 'avatar[filename]', readonly: 'readonly'} ).val(file.name),
- // $(' ').attr({ href: "#", 'class': 'remove-upload' }).click(removeFile).toggle(!eagerUpload)
- //).appendTo('#avatar_fields');
-
- if(eagerUpload) {
- ajaxUpload(file, fileSpan, inputEl);
- }
-
- return 1;
-}
-
-function ajaxUpload(file, fileSpan, inputEl) {
-
- function onLoadstart(e) {
- fileSpan.removeClass('ajax-waiting');
- fileSpan.addClass('ajax-loading');
- $('input:submit', $(this).parents('form')).attr('disabled', 'disabled');
- }
-
- function onProgress(e) {
- if(e.lengthComputable) {
- this.progressbar( 'value', e.loaded * 100 / e.total );
- }
- }
-
- function actualUpload(file, fileSpan, inputEl) {
-
- ajaxUpload.uploading++;
-
- uploadBlob(file, $(inputEl).data('upload-path'),$(inputEl).data('source-type'), $(inputEl).data('source-id'),{
- loadstartEventHandler: onLoadstart.bind(progressSpan),
- progressEventHandler: onProgress.bind(progressSpan)
- })
- .done(function(result) {
- progressSpan.progressbar( 'value', 100 );
- progressSpan.progressbar( 'destroy');
- fileSpan.find('input.description, a').css('display', 'inline-block');
- })
- .fail(function(result) {
- progressSpan.text(result.statusText);
- }).always(function() {
- ajaxUpload.uploading--;
- fileSpan.removeClass('ajax-loading');
- var form = fileSpan.parents('form');
- if (form.queue('upload').length == 0 && ajaxUpload.uploading == 0) {
- $('input:submit', form).removeAttr('disabled');
- }
- form.dequeue('upload');
- });
- }
-
- var progressSpan = $('#upload_progressbar');
- progressSpan.progressbar();
- fileSpan.addClass('ajax-waiting');
-
- var maxSyncUpload = $(inputEl).data('max-concurrent-uploads');
-
- if(maxSyncUpload == null || maxSyncUpload <= 0 || ajaxUpload.uploading < maxSyncUpload)
- actualUpload(file, fileSpan, inputEl);
- else
- $(inputEl).parents('form').queue('upload', actualUpload.bind(this, file, fileSpan, inputEl));
-}
-
-ajaxUpload.uploading = 0;
-
-function removeFile() {
- $(this).parent('span').remove();
- return false;
-}
-
-function uploadBlob(blob, uploadUrl, source_type,source_id, options) {
-
- var actualOptions = $.extend({
- loadstartEventHandler: $.noop,
- progressEventHandler: $.noop
- }, options);
-
- uploadUrl = uploadUrl + '?source_type=' + source_type + '&source_id=' + source_id;
- if (blob instanceof window.File) {
- uploadUrl += '&filename=' + encodeURIComponent(blob.name);
- }
-
- return $.ajax(uploadUrl, {
- type: 'POST',
- contentType: 'application/octet-stream',
- beforeSend: function(jqXhr) {
- jqXhr.setRequestHeader('Accept', 'application/js');
- },
- xhr: function() {
- var xhr = $.ajaxSettings.xhr();
- xhr.upload.onloadstart = actualOptions.loadstartEventHandler;
- xhr.upload.onprogress = actualOptions.progressEventHandler;
- return xhr;
- },
- data: blob,
- cache: false,
- processData: false
- });
-}
-
-function addInputAvatar(inputEl) {
-// var clearedFileInput = $(inputEl).clone().val('');
-
- if (inputEl.files) {
- // upload files using ajax
- uploadAndAttachFiles(inputEl.files, inputEl);
- // $(inputEl).remove();
- } else {
- // browser not supporting the file API, upload on form submission
- var avatarId;
- var aFilename = inputEl.value.split(/\/|\\/);
- avatarId = addFile(inputEl, { name: aFilename[ aFilename.length - 1 ] }, false);
- if (avatarId) {
- $(inputEl).attr({ name: 'avatar[file]', style: 'display:none;' }).appendTo('#avatar_image');
- }
- }
-
- //clearedFileInput.insertAfter('#avatars_fields');
-}
-
-
-function uploadAndAttachFiles(files, inputEl) {
-
- var maxFileSize = $(inputEl).data('max-file-size');
- var maxFileSizeExceeded = $(inputEl).data('max-file-size-message');
-
- var sizeExceeded = false;
- $.each(files, function() {
- if (this.size && maxFileSize && this.size > parseInt(maxFileSize)) {sizeExceeded=true;}
- });
- if (sizeExceeded) {
- window.alert(maxFileSizeExceeded);
- } else {
- $.each(files, function() {addFile(inputEl, this, true);});
- }
-}
-
-function handleFileDropEvent(e) {
-
- $(this).removeClass('fileover');
- blockEventPropagation(e);
-
- if ($.inArray('Files', e.dataTransfer.types) > -1) {
- uploadAndAttachFiles(e.dataTransfer.files, $('input:file.file_selector'));
- }
-}
-
-function dragOverHandler(e) {
- $(this).addClass('fileover');
- blockEventPropagation(e);
-}
-
-function dragOutHandler(e) {
- $(this).removeClass('fileover');
- blockEventPropagation(e);
-}
-
-function setupFileDrop() {
- if (window.File && window.FileList && window.ProgressEvent && window.FormData) {
-
- $.event.fixHooks.drop = { props: [ 'dataTransfer' ] };
-
- $('form div.box').has('input:file').each(function() {
- $(this).on({
- dragover: dragOverHandler,
- dragleave: dragOutHandler,
- drop: handleFileDropEvent
- });
- });
- }
-}
-
-$(document).ready(setupFileDrop);
diff --git a/trustie2/public/javascripts/bootstrap.min.js b/trustie2/public/javascripts/bootstrap.min.js
deleted file mode 100644
index 1a6258efc..000000000
--- a/trustie2/public/javascripts/bootstrap.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * Bootstrap v3.0.3 (http://getbootstrap.com)
- * Copyright 2013 Twitter, Inc.
- * Licensed under http://www.apache.org/licenses/LICENSE-2.0
- */
-
-if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]'),b=!0;if(a.length){var c=this.$element.find("input");"radio"===c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?b=!1:a.find(".active").removeClass("active")),b&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}b&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i ').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focus",i="hover"==g?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show),void 0):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide),void 0):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d="function"==typeof this.options.placement?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m="body"==this.options.container?window.innerWidth:j.outerWidth(),n="body"==this.options.container?window.innerHeight:j.outerHeight(),o="body"==this.options.container?0:j.offset().left;d="bottom"==d&&g.top+g.height+i-l>n?"top":"top"==d&&g.top-l-i<0?"bottom":"right"==d&&g.right+h>m?"left":"left"==d&&g.left-h '}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery);
\ No newline at end of file
diff --git a/trustie2/public/javascripts/bootstrap/affix.js b/trustie2/public/javascripts/bootstrap/affix.js
deleted file mode 100644
index 552bffa3f..000000000
--- a/trustie2/public/javascripts/bootstrap/affix.js
+++ /dev/null
@@ -1,126 +0,0 @@
-/* ========================================================================
- * Bootstrap: affix.js v3.0.3
- * http://getbootstrap.com/javascript/#affix
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // AFFIX CLASS DEFINITION
- // ======================
-
- var Affix = function (element, options) {
- this.options = $.extend({}, Affix.DEFAULTS, options)
- this.$window = $(window)
- .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
- .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
-
- this.$element = $(element)
- this.affixed =
- this.unpin = null
-
- this.checkPosition()
- }
-
- Affix.RESET = 'affix affix-top affix-bottom'
-
- Affix.DEFAULTS = {
- offset: 0
- }
-
- Affix.prototype.checkPositionWithEventLoop = function () {
- setTimeout($.proxy(this.checkPosition, this), 1)
- }
-
- Affix.prototype.checkPosition = function () {
- if (!this.$element.is(':visible')) return
-
- var scrollHeight = $(document).height()
- var scrollTop = this.$window.scrollTop()
- var position = this.$element.offset()
- var offset = this.options.offset
- var offsetTop = offset.top
- var offsetBottom = offset.bottom
-
- if (typeof offset != 'object') offsetBottom = offsetTop = offset
- if (typeof offsetTop == 'function') offsetTop = offset.top()
- if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
-
- var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :
- offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
- offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false
-
- if (this.affixed === affix) return
- if (this.unpin) this.$element.css('top', '')
-
- this.affixed = affix
- this.unpin = affix == 'bottom' ? position.top - scrollTop : null
-
- this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))
-
- if (affix == 'bottom') {
- this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })
- }
- }
-
-
- // AFFIX PLUGIN DEFINITION
- // =======================
-
- var old = $.fn.affix
-
- $.fn.affix = function (option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.affix')
- var options = typeof option == 'object' && option
-
- if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- $.fn.affix.Constructor = Affix
-
-
- // AFFIX NO CONFLICT
- // =================
-
- $.fn.affix.noConflict = function () {
- $.fn.affix = old
- return this
- }
-
-
- // AFFIX DATA-API
- // ==============
-
- $(window).on('load', function () {
- $('[data-spy="affix"]').each(function () {
- var $spy = $(this)
- var data = $spy.data()
-
- data.offset = data.offset || {}
-
- if (data.offsetBottom) data.offset.bottom = data.offsetBottom
- if (data.offsetTop) data.offset.top = data.offsetTop
-
- $spy.affix(data)
- })
- })
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/alert.js b/trustie2/public/javascripts/bootstrap/alert.js
deleted file mode 100644
index 695ad74d0..000000000
--- a/trustie2/public/javascripts/bootstrap/alert.js
+++ /dev/null
@@ -1,98 +0,0 @@
-/* ========================================================================
- * Bootstrap: alert.js v3.0.3
- * http://getbootstrap.com/javascript/#alerts
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // ALERT CLASS DEFINITION
- // ======================
-
- var dismiss = '[data-dismiss="alert"]'
- var Alert = function (el) {
- $(el).on('click', dismiss, this.close)
- }
-
- Alert.prototype.close = function (e) {
- var $this = $(this)
- var selector = $this.attr('data-target')
-
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
- }
-
- var $parent = $(selector)
-
- if (e) e.preventDefault()
-
- if (!$parent.length) {
- $parent = $this.hasClass('alert') ? $this : $this.parent()
- }
-
- $parent.trigger(e = $.Event('close.bs.alert'))
-
- if (e.isDefaultPrevented()) return
-
- $parent.removeClass('in')
-
- function removeElement() {
- $parent.trigger('closed.bs.alert').remove()
- }
-
- $.support.transition && $parent.hasClass('fade') ?
- $parent
- .one($.support.transition.end, removeElement)
- .emulateTransitionEnd(150) :
- removeElement()
- }
-
-
- // ALERT PLUGIN DEFINITION
- // =======================
-
- var old = $.fn.alert
-
- $.fn.alert = function (option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.alert')
-
- if (!data) $this.data('bs.alert', (data = new Alert(this)))
- if (typeof option == 'string') data[option].call($this)
- })
- }
-
- $.fn.alert.Constructor = Alert
-
-
- // ALERT NO CONFLICT
- // =================
-
- $.fn.alert.noConflict = function () {
- $.fn.alert = old
- return this
- }
-
-
- // ALERT DATA-API
- // ==============
-
- $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/bootstrap.min.js b/trustie2/public/javascripts/bootstrap/bootstrap.min.js
deleted file mode 100644
index 1a6258efc..000000000
--- a/trustie2/public/javascripts/bootstrap/bootstrap.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * Bootstrap v3.0.3 (http://getbootstrap.com)
- * Copyright 2013 Twitter, Inc.
- * Licensed under http://www.apache.org/licenses/LICENSE-2.0
- */
-
-if("undefined"==typeof jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]'),b=!0;if(a.length){var c=this.$element.find("input");"radio"===c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?b=!1:a.find(".active").removeClass("active")),b&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}b&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i ').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focus",i="hover"==g?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show),void 0):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide),void 0):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d="function"==typeof this.options.placement?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m="body"==this.options.container?window.innerWidth:j.outerWidth(),n="body"==this.options.container?window.innerHeight:j.outerHeight(),o="body"==this.options.container?0:j.offset().left;d="bottom"==d&&g.top+g.height+i-l>n?"top":"top"==d&&g.top-l-i<0?"bottom":"right"==d&&g.right+h>m?"left":"left"==d&&g.left-h '}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery);
\ No newline at end of file
diff --git a/trustie2/public/javascripts/bootstrap/button.js b/trustie2/public/javascripts/bootstrap/button.js
deleted file mode 100644
index c9fdde5e4..000000000
--- a/trustie2/public/javascripts/bootstrap/button.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/* ========================================================================
- * Bootstrap: button.js v3.0.3
- * http://getbootstrap.com/javascript/#buttons
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // BUTTON PUBLIC CLASS DEFINITION
- // ==============================
-
- var Button = function (element, options) {
- this.$element = $(element)
- this.options = $.extend({}, Button.DEFAULTS, options)
- }
-
- Button.DEFAULTS = {
- loadingText: 'loading...'
- }
-
- Button.prototype.setState = function (state) {
- var d = 'disabled'
- var $el = this.$element
- var val = $el.is('input') ? 'val' : 'html'
- var data = $el.data()
-
- state = state + 'Text'
-
- if (!data.resetText) $el.data('resetText', $el[val]())
-
- $el[val](data[state] || this.options[state])
-
- // push to event loop to allow forms to submit
- setTimeout(function () {
- state == 'loadingText' ?
- $el.addClass(d).attr(d, d) :
- $el.removeClass(d).removeAttr(d);
- }, 0)
- }
-
- Button.prototype.toggle = function () {
- var $parent = this.$element.closest('[data-toggle="buttons"]')
- var changed = true
-
- if ($parent.length) {
- var $input = this.$element.find('input')
- if ($input.prop('type') === 'radio') {
- // see if clicking on current one
- if ($input.prop('checked') && this.$element.hasClass('active'))
- changed = false
- else
- $parent.find('.active').removeClass('active')
- }
- if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
- }
-
- if (changed) this.$element.toggleClass('active')
- }
-
-
- // BUTTON PLUGIN DEFINITION
- // ========================
-
- var old = $.fn.button
-
- $.fn.button = function (option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.button')
- var options = typeof option == 'object' && option
-
- if (!data) $this.data('bs.button', (data = new Button(this, options)))
-
- if (option == 'toggle') data.toggle()
- else if (option) data.setState(option)
- })
- }
-
- $.fn.button.Constructor = Button
-
-
- // BUTTON NO CONFLICT
- // ==================
-
- $.fn.button.noConflict = function () {
- $.fn.button = old
- return this
- }
-
-
- // BUTTON DATA-API
- // ===============
-
- $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
- var $btn = $(e.target)
- if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
- $btn.button('toggle')
- e.preventDefault()
- })
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/carousel.js b/trustie2/public/javascripts/bootstrap/carousel.js
deleted file mode 100644
index 6391a36df..000000000
--- a/trustie2/public/javascripts/bootstrap/carousel.js
+++ /dev/null
@@ -1,217 +0,0 @@
-/* ========================================================================
- * Bootstrap: carousel.js v3.0.3
- * http://getbootstrap.com/javascript/#carousel
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // CAROUSEL CLASS DEFINITION
- // =========================
-
- var Carousel = function (element, options) {
- this.$element = $(element)
- this.$indicators = this.$element.find('.carousel-indicators')
- this.options = options
- this.paused =
- this.sliding =
- this.interval =
- this.$active =
- this.$items = null
-
- this.options.pause == 'hover' && this.$element
- .on('mouseenter', $.proxy(this.pause, this))
- .on('mouseleave', $.proxy(this.cycle, this))
- }
-
- Carousel.DEFAULTS = {
- interval: 5000
- , pause: 'hover'
- , wrap: true
- }
-
- Carousel.prototype.cycle = function (e) {
- e || (this.paused = false)
-
- this.interval && clearInterval(this.interval)
-
- this.options.interval
- && !this.paused
- && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
-
- return this
- }
-
- Carousel.prototype.getActiveIndex = function () {
- this.$active = this.$element.find('.item.active')
- this.$items = this.$active.parent().children()
-
- return this.$items.index(this.$active)
- }
-
- Carousel.prototype.to = function (pos) {
- var that = this
- var activeIndex = this.getActiveIndex()
-
- if (pos > (this.$items.length - 1) || pos < 0) return
-
- if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) })
- if (activeIndex == pos) return this.pause().cycle()
-
- return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
- }
-
- Carousel.prototype.pause = function (e) {
- e || (this.paused = true)
-
- if (this.$element.find('.next, .prev').length && $.support.transition.end) {
- this.$element.trigger($.support.transition.end)
- this.cycle(true)
- }
-
- this.interval = clearInterval(this.interval)
-
- return this
- }
-
- Carousel.prototype.next = function () {
- if (this.sliding) return
- return this.slide('next')
- }
-
- Carousel.prototype.prev = function () {
- if (this.sliding) return
- return this.slide('prev')
- }
-
- Carousel.prototype.slide = function (type, next) {
- var $active = this.$element.find('.item.active')
- var $next = next || $active[type]()
- var isCycling = this.interval
- var direction = type == 'next' ? 'left' : 'right'
- var fallback = type == 'next' ? 'first' : 'last'
- var that = this
-
- if (!$next.length) {
- if (!this.options.wrap) return
- $next = this.$element.find('.item')[fallback]()
- }
-
- this.sliding = true
-
- isCycling && this.pause()
-
- var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })
-
- if ($next.hasClass('active')) return
-
- if (this.$indicators.length) {
- this.$indicators.find('.active').removeClass('active')
- this.$element.one('slid.bs.carousel', function () {
- var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
- $nextIndicator && $nextIndicator.addClass('active')
- })
- }
-
- if ($.support.transition && this.$element.hasClass('slide')) {
- this.$element.trigger(e)
- if (e.isDefaultPrevented()) return
- $next.addClass(type)
- $next[0].offsetWidth // force reflow
- $active.addClass(direction)
- $next.addClass(direction)
- $active
- .one($.support.transition.end, function () {
- $next.removeClass([type, direction].join(' ')).addClass('active')
- $active.removeClass(['active', direction].join(' '))
- that.sliding = false
- setTimeout(function () { that.$element.trigger('slid.bs.carousel') }, 0)
- })
- .emulateTransitionEnd(600)
- } else {
- this.$element.trigger(e)
- if (e.isDefaultPrevented()) return
- $active.removeClass('active')
- $next.addClass('active')
- this.sliding = false
- this.$element.trigger('slid.bs.carousel')
- }
-
- isCycling && this.cycle()
-
- return this
- }
-
-
- // CAROUSEL PLUGIN DEFINITION
- // ==========================
-
- var old = $.fn.carousel
-
- $.fn.carousel = function (option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.carousel')
- var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
- var action = typeof option == 'string' ? option : options.slide
-
- if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
- if (typeof option == 'number') data.to(option)
- else if (action) data[action]()
- else if (options.interval) data.pause().cycle()
- })
- }
-
- $.fn.carousel.Constructor = Carousel
-
-
- // CAROUSEL NO CONFLICT
- // ====================
-
- $.fn.carousel.noConflict = function () {
- $.fn.carousel = old
- return this
- }
-
-
- // CAROUSEL DATA-API
- // =================
-
- $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
- var $this = $(this), href
- var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
- var options = $.extend({}, $target.data(), $this.data())
- var slideIndex = $this.attr('data-slide-to')
- if (slideIndex) options.interval = false
-
- $target.carousel(options)
-
- if (slideIndex = $this.attr('data-slide-to')) {
- $target.data('bs.carousel').to(slideIndex)
- }
-
- e.preventDefault()
- })
-
- $(window).on('load', function () {
- $('[data-ride="carousel"]').each(function () {
- var $carousel = $(this)
- $carousel.carousel($carousel.data())
- })
- })
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/collapse.js b/trustie2/public/javascripts/bootstrap/collapse.js
deleted file mode 100644
index 1a079938e..000000000
--- a/trustie2/public/javascripts/bootstrap/collapse.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/* ========================================================================
- * Bootstrap: collapse.js v3.0.3
- * http://getbootstrap.com/javascript/#collapse
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // COLLAPSE PUBLIC CLASS DEFINITION
- // ================================
-
- var Collapse = function (element, options) {
- this.$element = $(element)
- this.options = $.extend({}, Collapse.DEFAULTS, options)
- this.transitioning = null
-
- if (this.options.parent) this.$parent = $(this.options.parent)
- if (this.options.toggle) this.toggle()
- }
-
- Collapse.DEFAULTS = {
- toggle: true
- }
-
- Collapse.prototype.dimension = function () {
- var hasWidth = this.$element.hasClass('width')
- return hasWidth ? 'width' : 'height'
- }
-
- Collapse.prototype.show = function () {
- if (this.transitioning || this.$element.hasClass('in')) return
-
- var startEvent = $.Event('show.bs.collapse')
- this.$element.trigger(startEvent)
- if (startEvent.isDefaultPrevented()) return
-
- var actives = this.$parent && this.$parent.find('> .panel > .in')
-
- if (actives && actives.length) {
- var hasData = actives.data('bs.collapse')
- if (hasData && hasData.transitioning) return
- actives.collapse('hide')
- hasData || actives.data('bs.collapse', null)
- }
-
- var dimension = this.dimension()
-
- this.$element
- .removeClass('collapse')
- .addClass('collapsing')
- [dimension](0)
-
- this.transitioning = 1
-
- var complete = function () {
- this.$element
- .removeClass('collapsing')
- .addClass('in')
- [dimension]('auto')
- this.transitioning = 0
- this.$element.trigger('shown.bs.collapse')
- }
-
- if (!$.support.transition) return complete.call(this)
-
- var scrollSize = $.camelCase(['scroll', dimension].join('-'))
-
- this.$element
- .one($.support.transition.end, $.proxy(complete, this))
- .emulateTransitionEnd(350)
- [dimension](this.$element[0][scrollSize])
- }
-
- Collapse.prototype.hide = function () {
- if (this.transitioning || !this.$element.hasClass('in')) return
-
- var startEvent = $.Event('hide.bs.collapse')
- this.$element.trigger(startEvent)
- if (startEvent.isDefaultPrevented()) return
-
- var dimension = this.dimension()
-
- this.$element
- [dimension](this.$element[dimension]())
- [0].offsetHeight
-
- this.$element
- .addClass('collapsing')
- .removeClass('collapse')
- .removeClass('in')
-
- this.transitioning = 1
-
- var complete = function () {
- this.transitioning = 0
- this.$element
- .trigger('hidden.bs.collapse')
- .removeClass('collapsing')
- .addClass('collapse')
- }
-
- if (!$.support.transition) return complete.call(this)
-
- this.$element
- [dimension](0)
- .one($.support.transition.end, $.proxy(complete, this))
- .emulateTransitionEnd(350)
- }
-
- Collapse.prototype.toggle = function () {
- this[this.$element.hasClass('in') ? 'hide' : 'show']()
- }
-
-
- // COLLAPSE PLUGIN DEFINITION
- // ==========================
-
- var old = $.fn.collapse
-
- $.fn.collapse = function (option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.collapse')
- var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
-
- if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- $.fn.collapse.Constructor = Collapse
-
-
- // COLLAPSE NO CONFLICT
- // ====================
-
- $.fn.collapse.noConflict = function () {
- $.fn.collapse = old
- return this
- }
-
-
- // COLLAPSE DATA-API
- // =================
-
- $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {
- var $this = $(this), href
- var target = $this.attr('data-target')
- || e.preventDefault()
- || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
- var $target = $(target)
- var data = $target.data('bs.collapse')
- var option = data ? 'toggle' : $this.data()
- var parent = $this.attr('data-parent')
- var $parent = parent && $(parent)
-
- if (!data || !data.transitioning) {
- if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed')
- $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
- }
-
- $target.collapse(option)
- })
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/dropdown.js b/trustie2/public/javascripts/bootstrap/dropdown.js
deleted file mode 100644
index 13352ef7c..000000000
--- a/trustie2/public/javascripts/bootstrap/dropdown.js
+++ /dev/null
@@ -1,154 +0,0 @@
-/* ========================================================================
- * Bootstrap: dropdown.js v3.0.3
- * http://getbootstrap.com/javascript/#dropdowns
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // DROPDOWN CLASS DEFINITION
- // =========================
-
- var backdrop = '.dropdown-backdrop'
- var toggle = '[data-toggle=dropdown]'
- var Dropdown = function (element) {
- $(element).on('click.bs.dropdown', this.toggle)
- }
-
- Dropdown.prototype.toggle = function (e) {
- var $this = $(this)
-
- if ($this.is('.disabled, :disabled')) return
-
- var $parent = getParent($this)
- var isActive = $parent.hasClass('open')
-
- clearMenus()
-
- if (!isActive) {
- if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
- // if mobile we use a backdrop because click events don't delegate
- $('').insertAfter($(this)).on('click', clearMenus)
- }
-
- $parent.trigger(e = $.Event('show.bs.dropdown'))
-
- if (e.isDefaultPrevented()) return
-
- $parent
- .toggleClass('open')
- .trigger('shown.bs.dropdown')
-
- $this.focus()
- }
-
- return false
- }
-
- Dropdown.prototype.keydown = function (e) {
- if (!/(38|40|27)/.test(e.keyCode)) return
-
- var $this = $(this)
-
- e.preventDefault()
- e.stopPropagation()
-
- if ($this.is('.disabled, :disabled')) return
-
- var $parent = getParent($this)
- var isActive = $parent.hasClass('open')
-
- if (!isActive || (isActive && e.keyCode == 27)) {
- if (e.which == 27) $parent.find(toggle).focus()
- return $this.click()
- }
-
- var $items = $('[role=menu] li:not(.divider):visible a', $parent)
-
- if (!$items.length) return
-
- var index = $items.index($items.filter(':focus'))
-
- if (e.keyCode == 38 && index > 0) index-- // up
- if (e.keyCode == 40 && index < $items.length - 1) index++ // down
- if (!~index) index=0
-
- $items.eq(index).focus()
- }
-
- function clearMenus() {
- $(backdrop).remove()
- $(toggle).each(function (e) {
- var $parent = getParent($(this))
- if (!$parent.hasClass('open')) return
- $parent.trigger(e = $.Event('hide.bs.dropdown'))
- if (e.isDefaultPrevented()) return
- $parent.removeClass('open').trigger('hidden.bs.dropdown')
- })
- }
-
- function getParent($this) {
- var selector = $this.attr('data-target')
-
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
- }
-
- var $parent = selector && $(selector)
-
- return $parent && $parent.length ? $parent : $this.parent()
- }
-
-
- // DROPDOWN PLUGIN DEFINITION
- // ==========================
-
- var old = $.fn.dropdown
-
- $.fn.dropdown = function (option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.dropdown')
-
- if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
- if (typeof option == 'string') data[option].call($this)
- })
- }
-
- $.fn.dropdown.Constructor = Dropdown
-
-
- // DROPDOWN NO CONFLICT
- // ====================
-
- $.fn.dropdown.noConflict = function () {
- $.fn.dropdown = old
- return this
- }
-
-
- // APPLY TO STANDARD DROPDOWN ELEMENTS
- // ===================================
-
- $(document)
- .on('click.bs.dropdown.data-api', clearMenus)
- .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
- .on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
- .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/jquery.transition.min.js b/trustie2/public/javascripts/bootstrap/jquery.transition.min.js
deleted file mode 100644
index 096b426ba..000000000
--- a/trustie2/public/javascripts/bootstrap/jquery.transition.min.js
+++ /dev/null
@@ -1 +0,0 @@
-(function(a){function t(){setTimeout(x,0);return m=a.now()}function x(){m=void 0}var r={},k,q,y=/^(?:toggle|show|hide)$/,z=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,u,m,v=document.createElement("div").style,w;a.support.transition="MozTransition"in v?"MozTransition":"WebkitTransition"in v?"WebkitTransition":!1;a.cssNumber.color=a.cssNumber.backgroundColor=!0;w={linear:"linear",swing:"ease-out",bounce:"cubic-bezier(0,.35,.5,1.3)",easeInQuad:"cubic-bezier(.55,.085,.68,.53)",easeInCubic:"cubic-bezier(.55,.055,.675,.19)", easeInQuart:"cubic-bezier(.895,.03,.685,.22)",easeInQuint:"cubic-bezier(.755,.05,.855,.06)",easeInSine:"cubic-bezier(.47,0,.745,.715)",easeInExpo:"cubic-bezier(.95,.05,.795,.035)",easeInCirc:"cubic-bezier(.6,.04,.98,.335)",easeOutQuad:"cubic-bezier(.25,.46,.45,.94)",easeOutCubic:"cubic-bezier(.215,.61,.355,1)",easeOutQuart:"cubic-bezier(.165,.84,.44,1)",easeOutQuint:"cubic-bezier(.23,1,.32,1)",easeOutSine:"cubic-bezier(.39,.575,.565,1)",easeOutExpo:"cubic-bezier(.19,1,.22,1)",easeOutCirc:"cubic-bezier(.075,.82,.165,1)", easeInOutQuad:"cubic-bezier(.455,.03,.515,.955)",easeInOutCubic:"cubic-bezier(.645,.045,.355,1)",easeInOutQuart:"cubic-bezier(.77,0,.175,1)",easeInOutQuint:"cubic-bezier(.86,0,.07,1)",easeInOutSine:"cubic-bezier(.445,.05,.55,.95)",easeInOutExpo:"cubic-bezier(1,0,0,1)",easeInOutCirc:"cubic-bezier(.785,.135,.15,.86)"};a.fn.extend({animate:function(d,e,g,b){function f(){!1===i.queue&&a._mark(this);var c=a.extend({},i),f=1===this.nodeType,e=f&&a(this).is(":hidden"),b,h,g,j,n;n=a.cssProps;var m=!c.step&& a.support.transition,s=[],o,p;c.animatedProperties={};c.transition={};for(g in d)if(b=a.camelCase(g),g!==b&&(d[b]=d[g],delete d[g]),(h=a.cssHooks[b])&&"expand"in h)for(g in j=h.expand(d[b]),delete d[b],j)g in d||(d[g]=j[g]);for(b in d){h=d[b];a.isArray(h)?(j=c.animatedProperties[b]=h[1],h=d[b]=h[0]):j=c.animatedProperties[b]=c.specialEasing&&c.specialEasing[b]||c.easing||"swing";if(j=m&&f&&0").appendTo(j);p=o.css("display");o.remove();if("none"===p||""===p){k||(k=document.createElement("iframe"),k.frameBorder= k.width=k.height=0);j.appendChild(k);if(!q||!k.createElement)q=(k.contentWindow||k.contentDocument).document,q.write((a.support.boxModel?"":"")+""),q.close();o=q.createElement(h);q.body.appendChild(o);p=a.css(o,"display");j.removeChild(k)}r[h]=p}h="inline"===r[h]}h?this.style.display="inline-block":this.style.zoom=1}}null!=c.overflow&&(this.style.overflow="hidden");for(g in d)if(f=new a.fx(this,c,g),h=d[g],y.test(h))if(b=a._data(this,"toggle"+g)||("toggle"===h?e?"show": "hide":0))a._data(this,"toggle"+g,"show"===b?"hide":"show"),f[b]();else f[h]();else b=z.exec(h),n=f.cur(),b?(h=parseFloat(b[2]),j=b[3]||(a.cssNumber[g]?"":"px"),"px"!==j&&(a.style(this,g,(h||1)+j),n*=(h||1)/f.cur(),a.style(this,g,n+j)),b[1]&&(h=("-="===b[1]?-1:1)*h+n),f.custom(n,h,j)):f.custom(n,h,"");if(m&&s.length)for(g in j=this.style[m],e=window.getComputedStyle(this),this.style[m]=s.join()+(j&&j.indexOf("none")?","+j:""),c.transition)e[g],a.style.apply(null,c.transition[g].styleToSet);return!0} var i=a.speed(e,g,b);if(a.isEmptyObject(d))return this.each(i.complete,[!1]);d=a.extend({},d);return!1===i.queue?this.each(f):this.queue(i.queue,f)},stop:function(d,e,g){"string"!==typeof d&&(g=e,e=d,d=void 0);e&&!1!==d&&this.queue(d||"fx",[]);return this.each(function(){var b,f=false,e=a.timers,c=a._data(this),l=a.support.transition;g||a._unmark(true,this);if(d==null)for(b in c){if(c[b]&&c[b].stop&&b.indexOf(".run")===b.length-4){var k=c[b];a.removeData(this,b,true);k.stop(g)}}else if(c[b=d+".run"]&& c[b].stop){c=c[b];a.removeData(this,b,true);c.stop(g)}for(b=e.length;b--;)if(e[b].elem===this&&(d==null||e[b].queue===d)){if(g||l)e[b](g);g||e[b].saveState();f=true;e.splice(b,1)}(!g||!f)&&a.dequeue(this,d)})}});a.extend(a.fx.prototype,{cur:function(){if(null!=this.elem[this.prop]&&(!this.elem.style||null==this.elem.style[this.prop]))return this.elem[this.prop];var d,e=a.css(this.elem,this.prop);return isNaN(d=parseFloat(e))?!e||"auto"===e?0:e:d},custom:function(d,e,g){function b(a){return f.step(a)} var f=this,i=a.fx,c=f.options.transition,l=this.prop;this.startTime=m||t();this.end=e;this.now=this.start=d;this.pos=this.state=0;this.unit=g||this.unit||(a.cssNumber[l]?"":"px");b.queue=this.options.queue;b.elem=this.elem;b.saveState=function(){void 0===a._data(f.elem,"fxshow"+f.prop)&&(f.options.hide?a._data(f.elem,"fxshow"+f.prop,f.start):f.options.show&&a._data(f.elem,"fxshow"+f.prop,f.end))};(b.transition=c[l])?(a.timers.push(b),"transform"!=l&&(f.elem.style[c[l].real]=d+f.unit),a.fx.step[l]&& (e=Math.max(0,e)),c[l].styleToSet=[f.elem,l,e+f.unit],c[l].timeout=setTimeout(function(){a.timers.splice(a.timers.indexOf(b),1);f.step(!0)},f.options.duration+30)):b()&&a.timers.push(b)&&!u&&(u=setInterval(i.tick,i.interval))},step:function(d){var e,g=m||t(),b=!0,f=this.elem,i=this.options,c=i.transition[this.prop],l=g>=i.duration+this.startTime,k=a.support.transition;if(c||d||l){c?(clearTimeout(c.timeout),!d&&!l&&(this.elem.style[c.real]=a.css(this.elem,c.real))):(this.now=this.end,this.pos=this.state= 1,this.update());i.animatedProperties[this.prop]=!0;for(e in i.animatedProperties)!0!==i.animatedProperties[e]&&(b=!1);if(b){null!=i.overflow&&!a.support.shrinkWrapBlocks&&a.each(["","X","Y"],function(a,b){f.style["overflow"+b]=i.overflow[a]});i.hide&&a(f).hide();if(c){c=","+f.style[k];for(e in i.transition)c=c.split(i.transition[e].lower).join("_");c=c.replace(/, ?_[^,]*/g,"").substr(1);f.style[k]=c||"none";!c&&(f.style[k]=c)}if(i.hide||i.show)for(e in i.animatedProperties)(d||l)&&a.style(f,e,i.orig[e]), a.removeData(f,"fxshow"+e,!0),a.removeData(f,"toggle"+e,!0);if((e=i.complete)&&(d||l))i.complete=!1,e.call(f)}return!1}Infinity==i.duration?this.now=g:(d=g-this.startTime,this.state=d/i.duration,this.pos=a.easing[i.animatedProperties[this.prop]](this.state,d,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos);this.update();return!0}});a.extend(a.fx,{tick:function(){for(var d,e=a.timers,g=0;g ')
- .appendTo(document.body)
-
- this.$element.on('click.dismiss.modal', $.proxy(function (e) {
- if (e.target !== e.currentTarget) return
- this.options.backdrop == 'static'
- ? this.$element[0].focus.call(this.$element[0])
- : this.hide.call(this)
- }, this))
-
- if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
-
- this.$backdrop.addClass('in')
-
- if (!callback) return
-
- doAnimate ?
- this.$backdrop
- .one($.support.transition.end, callback)
- .emulateTransitionEnd(150) :
- callback()
-
- } else if (!this.isShown && this.$backdrop) {
- this.$backdrop.removeClass('in')
-
- $.support.transition && this.$element.hasClass('fade')?
- this.$backdrop
- .one($.support.transition.end, callback)
- .emulateTransitionEnd(150) :
- callback()
-
- } else if (callback) {
- callback()
- }
- }
-
-
- // MODAL PLUGIN DEFINITION
- // =======================
-
- var old = $.fn.modal
-
- $.fn.modal = function (option, _relatedTarget) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.modal')
- var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
-
- if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
- if (typeof option == 'string') data[option](_relatedTarget)
- else if (options.show) data.show(_relatedTarget)
- })
- }
-
- $.fn.modal.Constructor = Modal
-
-
- // MODAL NO CONFLICT
- // =================
-
- $.fn.modal.noConflict = function () {
- $.fn.modal = old
- return this
- }
-
-
- // MODAL DATA-API
- // ==============
-
- $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
- var $this = $(this)
- var href = $this.attr('href')
- var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
- var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
-
- e.preventDefault()
-
- $target
- .modal(option, this)
- .one('hide', function () {
- $this.is(':visible') && $this.focus()
- })
- })
-
- $(document)
- .on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') })
- .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/popover.js b/trustie2/public/javascripts/bootstrap/popover.js
deleted file mode 100644
index 996962aa2..000000000
--- a/trustie2/public/javascripts/bootstrap/popover.js
+++ /dev/null
@@ -1,117 +0,0 @@
-/* ========================================================================
- * Bootstrap: popover.js v3.0.3
- * http://getbootstrap.com/javascript/#popovers
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // POPOVER PUBLIC CLASS DEFINITION
- // ===============================
-
- var Popover = function (element, options) {
- this.init('popover', element, options)
- }
-
- if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
-
- Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {
- placement: 'right'
- , trigger: 'click'
- , content: ''
- , template: ''
- })
-
-
- // NOTE: POPOVER EXTENDS tooltip.js
- // ================================
-
- Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
-
- Popover.prototype.constructor = Popover
-
- Popover.prototype.getDefaults = function () {
- return Popover.DEFAULTS
- }
-
- Popover.prototype.setContent = function () {
- var $tip = this.tip()
- var title = this.getTitle()
- var content = this.getContent()
-
- $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
- $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
-
- $tip.removeClass('fade top bottom left right in')
-
- // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
- // this manually by checking the contents.
- if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
- }
-
- Popover.prototype.hasContent = function () {
- return this.getTitle() || this.getContent()
- }
-
- Popover.prototype.getContent = function () {
- var $e = this.$element
- var o = this.options
-
- return $e.attr('data-content')
- || (typeof o.content == 'function' ?
- o.content.call($e[0]) :
- o.content)
- }
-
- Popover.prototype.arrow = function () {
- return this.$arrow = this.$arrow || this.tip().find('.arrow')
- }
-
- Popover.prototype.tip = function () {
- if (!this.$tip) this.$tip = $(this.options.template)
- return this.$tip
- }
-
-
- // POPOVER PLUGIN DEFINITION
- // =========================
-
- var old = $.fn.popover
-
- $.fn.popover = function (option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.popover')
- var options = typeof option == 'object' && option
-
- if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- $.fn.popover.Constructor = Popover
-
-
- // POPOVER NO CONFLICT
- // ===================
-
- $.fn.popover.noConflict = function () {
- $.fn.popover = old
- return this
- }
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/scrollspy.js b/trustie2/public/javascripts/bootstrap/scrollspy.js
deleted file mode 100644
index 2efe14fdd..000000000
--- a/trustie2/public/javascripts/bootstrap/scrollspy.js
+++ /dev/null
@@ -1,158 +0,0 @@
-/* ========================================================================
- * Bootstrap: scrollspy.js v3.0.3
- * http://getbootstrap.com/javascript/#scrollspy
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // SCROLLSPY CLASS DEFINITION
- // ==========================
-
- function ScrollSpy(element, options) {
- var href
- var process = $.proxy(this.process, this)
-
- this.$element = $(element).is('body') ? $(window) : $(element)
- this.$body = $('body')
- this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)
- this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
- this.selector = (this.options.target
- || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
- || '') + ' .nav li > a'
- this.offsets = $([])
- this.targets = $([])
- this.activeTarget = null
-
- this.refresh()
- this.process()
- }
-
- ScrollSpy.DEFAULTS = {
- offset: 10
- }
-
- ScrollSpy.prototype.refresh = function () {
- var offsetMethod = this.$element[0] == window ? 'offset' : 'position'
-
- this.offsets = $([])
- this.targets = $([])
-
- var self = this
- var $targets = this.$body
- .find(this.selector)
- .map(function () {
- var $el = $(this)
- var href = $el.data('target') || $el.attr('href')
- var $href = /^#\w/.test(href) && $(href)
-
- return ($href
- && $href.length
- && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null
- })
- .sort(function (a, b) { return a[0] - b[0] })
- .each(function () {
- self.offsets.push(this[0])
- self.targets.push(this[1])
- })
- }
-
- ScrollSpy.prototype.process = function () {
- var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
- var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
- var maxScroll = scrollHeight - this.$scrollElement.height()
- var offsets = this.offsets
- var targets = this.targets
- var activeTarget = this.activeTarget
- var i
-
- if (scrollTop >= maxScroll) {
- return activeTarget != (i = targets.last()[0]) && this.activate(i)
- }
-
- for (i = offsets.length; i--;) {
- activeTarget != targets[i]
- && scrollTop >= offsets[i]
- && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
- && this.activate( targets[i] )
- }
- }
-
- ScrollSpy.prototype.activate = function (target) {
- this.activeTarget = target
-
- $(this.selector)
- .parents('.active')
- .removeClass('active')
-
- var selector = this.selector
- + '[data-target="' + target + '"],'
- + this.selector + '[href="' + target + '"]'
-
- var active = $(selector)
- .parents('li')
- .addClass('active')
-
- if (active.parent('.dropdown-menu').length) {
- active = active
- .closest('li.dropdown')
- .addClass('active')
- }
-
- active.trigger('activate.bs.scrollspy')
- }
-
-
- // SCROLLSPY PLUGIN DEFINITION
- // ===========================
-
- var old = $.fn.scrollspy
-
- $.fn.scrollspy = function (option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.scrollspy')
- var options = typeof option == 'object' && option
-
- if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- $.fn.scrollspy.Constructor = ScrollSpy
-
-
- // SCROLLSPY NO CONFLICT
- // =====================
-
- $.fn.scrollspy.noConflict = function () {
- $.fn.scrollspy = old
- return this
- }
-
-
- // SCROLLSPY DATA-API
- // ==================
-
- $(window).on('load', function () {
- $('[data-spy="scroll"]').each(function () {
- var $spy = $(this)
- $spy.scrollspy($spy.data())
- })
- })
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/tab.js b/trustie2/public/javascripts/bootstrap/tab.js
deleted file mode 100644
index 6b0f5f672..000000000
--- a/trustie2/public/javascripts/bootstrap/tab.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/* ========================================================================
- * Bootstrap: tab.js v3.0.3
- * http://getbootstrap.com/javascript/#tabs
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // TAB CLASS DEFINITION
- // ====================
-
- var Tab = function (element) {
- this.element = $(element)
- }
-
- Tab.prototype.show = function () {
- var $this = this.element
- var $ul = $this.closest('ul:not(.dropdown-menu)')
- var selector = $this.data('target')
-
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
- }
-
- if ($this.parent('li').hasClass('active')) return
-
- var previous = $ul.find('.active:last a')[0]
- var e = $.Event('show.bs.tab', {
- relatedTarget: previous
- })
-
- $this.trigger(e)
-
- if (e.isDefaultPrevented()) return
-
- var $target = $(selector)
-
- this.activate($this.parent('li'), $ul)
- this.activate($target, $target.parent(), function () {
- $this.trigger({
- type: 'shown.bs.tab'
- , relatedTarget: previous
- })
- })
- }
-
- Tab.prototype.activate = function (element, container, callback) {
- var $active = container.find('> .active')
- var transition = callback
- && $.support.transition
- && $active.hasClass('fade')
-
- function next() {
- $active
- .removeClass('active')
- .find('> .dropdown-menu > .active')
- .removeClass('active')
-
- element.addClass('active')
-
- if (transition) {
- element[0].offsetWidth // reflow for transition
- element.addClass('in')
- } else {
- element.removeClass('fade')
- }
-
- if (element.parent('.dropdown-menu')) {
- element.closest('li.dropdown').addClass('active')
- }
-
- callback && callback()
- }
-
- transition ?
- $active
- .one($.support.transition.end, next)
- .emulateTransitionEnd(150) :
- next()
-
- $active.removeClass('in')
- }
-
-
- // TAB PLUGIN DEFINITION
- // =====================
-
- var old = $.fn.tab
-
- $.fn.tab = function ( option ) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.tab')
-
- if (!data) $this.data('bs.tab', (data = new Tab(this)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- $.fn.tab.Constructor = Tab
-
-
- // TAB NO CONFLICT
- // ===============
-
- $.fn.tab.noConflict = function () {
- $.fn.tab = old
- return this
- }
-
-
- // TAB DATA-API
- // ============
-
- $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
- e.preventDefault()
- $(this).tab('show')
- })
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/tooltip.js b/trustie2/public/javascripts/bootstrap/tooltip.js
deleted file mode 100644
index 4c848f0e2..000000000
--- a/trustie2/public/javascripts/bootstrap/tooltip.js
+++ /dev/null
@@ -1,386 +0,0 @@
-/* ========================================================================
- * Bootstrap: tooltip.js v3.0.3
- * http://getbootstrap.com/javascript/#tooltip
- * Inspired by the original jQuery.tipsy by Jason Frame
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // TOOLTIP PUBLIC CLASS DEFINITION
- // ===============================
-
- var Tooltip = function (element, options) {
- this.type =
- this.options =
- this.enabled =
- this.timeout =
- this.hoverState =
- this.$element = null
-
- this.init('tooltip', element, options)
- }
-
- Tooltip.DEFAULTS = {
- animation: true
- , placement: 'top'
- , selector: false
- , template: ''
- , trigger: 'hover focus'
- , title: ''
- , delay: 0
- , html: false
- , container: false
- }
-
- Tooltip.prototype.init = function (type, element, options) {
- this.enabled = true
- this.type = type
- this.$element = $(element)
- this.options = this.getOptions(options)
-
- var triggers = this.options.trigger.split(' ')
-
- for (var i = triggers.length; i--;) {
- var trigger = triggers[i]
-
- if (trigger == 'click') {
- this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
- } else if (trigger != 'manual') {
- var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
- var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
-
- this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
- this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
- }
- }
-
- this.options.selector ?
- (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
- this.fixTitle()
- }
-
- Tooltip.prototype.getDefaults = function () {
- return Tooltip.DEFAULTS
- }
-
- Tooltip.prototype.getOptions = function (options) {
- options = $.extend({}, this.getDefaults(), this.$element.data(), options)
-
- if (options.delay && typeof options.delay == 'number') {
- options.delay = {
- show: options.delay
- , hide: options.delay
- }
- }
-
- return options
- }
-
- Tooltip.prototype.getDelegateOptions = function () {
- var options = {}
- var defaults = this.getDefaults()
-
- this._options && $.each(this._options, function (key, value) {
- if (defaults[key] != value) options[key] = value
- })
-
- return options
- }
-
- Tooltip.prototype.enter = function (obj) {
- var self = obj instanceof this.constructor ?
- obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
-
- clearTimeout(self.timeout)
-
- self.hoverState = 'in'
-
- if (!self.options.delay || !self.options.delay.show) return self.show()
-
- self.timeout = setTimeout(function () {
- if (self.hoverState == 'in') self.show()
- }, self.options.delay.show)
- }
-
- Tooltip.prototype.leave = function (obj) {
- var self = obj instanceof this.constructor ?
- obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
-
- clearTimeout(self.timeout)
-
- self.hoverState = 'out'
-
- if (!self.options.delay || !self.options.delay.hide) return self.hide()
-
- self.timeout = setTimeout(function () {
- if (self.hoverState == 'out') self.hide()
- }, self.options.delay.hide)
- }
-
- Tooltip.prototype.show = function () {
- var e = $.Event('show.bs.'+ this.type)
-
- if (this.hasContent() && this.enabled) {
- this.$element.trigger(e)
-
- if (e.isDefaultPrevented()) return
-
- var $tip = this.tip()
-
- this.setContent()
-
- if (this.options.animation) $tip.addClass('fade')
-
- var placement = typeof this.options.placement == 'function' ?
- this.options.placement.call(this, $tip[0], this.$element[0]) :
- this.options.placement
-
- var autoToken = /\s?auto?\s?/i
- var autoPlace = autoToken.test(placement)
- if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
-
- $tip
- .detach()
- .css({ top: 0, left: 0, display: 'block' })
- .addClass(placement)
-
- this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
-
- var pos = this.getPosition()
- var actualWidth = $tip[0].offsetWidth
- var actualHeight = $tip[0].offsetHeight
-
- if (autoPlace) {
- var $parent = this.$element.parent()
-
- var orgPlacement = placement
- var docScroll = document.documentElement.scrollTop || document.body.scrollTop
- var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth()
- var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
- var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left
-
- placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
- placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
- placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
- placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
- placement
-
- $tip
- .removeClass(orgPlacement)
- .addClass(placement)
- }
-
- var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
-
- this.applyPlacement(calculatedOffset, placement)
- this.$element.trigger('shown.bs.' + this.type)
- }
- }
-
- Tooltip.prototype.applyPlacement = function(offset, placement) {
- var replace
- var $tip = this.tip()
- var width = $tip[0].offsetWidth
- var height = $tip[0].offsetHeight
-
- // manually read margins because getBoundingClientRect includes difference
- var marginTop = parseInt($tip.css('margin-top'), 10)
- var marginLeft = parseInt($tip.css('margin-left'), 10)
-
- // we must check for NaN for ie 8/9
- if (isNaN(marginTop)) marginTop = 0
- if (isNaN(marginLeft)) marginLeft = 0
-
- offset.top = offset.top + marginTop
- offset.left = offset.left + marginLeft
-
- $tip
- .offset(offset)
- .addClass('in')
-
- // check to see if placing tip in new offset caused the tip to resize itself
- var actualWidth = $tip[0].offsetWidth
- var actualHeight = $tip[0].offsetHeight
-
- if (placement == 'top' && actualHeight != height) {
- replace = true
- offset.top = offset.top + height - actualHeight
- }
-
- if (/bottom|top/.test(placement)) {
- var delta = 0
-
- if (offset.left < 0) {
- delta = offset.left * -2
- offset.left = 0
-
- $tip.offset(offset)
-
- actualWidth = $tip[0].offsetWidth
- actualHeight = $tip[0].offsetHeight
- }
-
- this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
- } else {
- this.replaceArrow(actualHeight - height, actualHeight, 'top')
- }
-
- if (replace) $tip.offset(offset)
- }
-
- Tooltip.prototype.replaceArrow = function(delta, dimension, position) {
- this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
- }
-
- Tooltip.prototype.setContent = function () {
- var $tip = this.tip()
- var title = this.getTitle()
-
- $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
- $tip.removeClass('fade in top bottom left right')
- }
-
- Tooltip.prototype.hide = function () {
- var that = this
- var $tip = this.tip()
- var e = $.Event('hide.bs.' + this.type)
-
- function complete() {
- if (that.hoverState != 'in') $tip.detach()
- }
-
- this.$element.trigger(e)
-
- if (e.isDefaultPrevented()) return
-
- $tip.removeClass('in')
-
- $.support.transition && this.$tip.hasClass('fade') ?
- $tip
- .one($.support.transition.end, complete)
- .emulateTransitionEnd(150) :
- complete()
-
- this.$element.trigger('hidden.bs.' + this.type)
-
- return this
- }
-
- Tooltip.prototype.fixTitle = function () {
- var $e = this.$element
- if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
- $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
- }
- }
-
- Tooltip.prototype.hasContent = function () {
- return this.getTitle()
- }
-
- Tooltip.prototype.getPosition = function () {
- var el = this.$element[0]
- return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
- width: el.offsetWidth
- , height: el.offsetHeight
- }, this.$element.offset())
- }
-
- Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
- return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
- placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
- placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
- /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
- }
-
- Tooltip.prototype.getTitle = function () {
- var title
- var $e = this.$element
- var o = this.options
-
- title = $e.attr('data-original-title')
- || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
-
- return title
- }
-
- Tooltip.prototype.tip = function () {
- return this.$tip = this.$tip || $(this.options.template)
- }
-
- Tooltip.prototype.arrow = function () {
- return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
- }
-
- Tooltip.prototype.validate = function () {
- if (!this.$element[0].parentNode) {
- this.hide()
- this.$element = null
- this.options = null
- }
- }
-
- Tooltip.prototype.enable = function () {
- this.enabled = true
- }
-
- Tooltip.prototype.disable = function () {
- this.enabled = false
- }
-
- Tooltip.prototype.toggleEnabled = function () {
- this.enabled = !this.enabled
- }
-
- Tooltip.prototype.toggle = function (e) {
- var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
- }
-
- Tooltip.prototype.destroy = function () {
- this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
- }
-
-
- // TOOLTIP PLUGIN DEFINITION
- // =========================
-
- var old = $.fn.tooltip
-
- $.fn.tooltip = function (option) {
- return this.each(function () {
- var $this = $(this)
- var data = $this.data('bs.tooltip')
- var options = typeof option == 'object' && option
-
- if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
- if (typeof option == 'string') data[option]()
- })
- }
-
- $.fn.tooltip.Constructor = Tooltip
-
-
- // TOOLTIP NO CONFLICT
- // ===================
-
- $.fn.tooltip.noConflict = function () {
- $.fn.tooltip = old
- return this
- }
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/bootstrap/transition.js b/trustie2/public/javascripts/bootstrap/transition.js
deleted file mode 100644
index 773dbe693..000000000
--- a/trustie2/public/javascripts/bootstrap/transition.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/* ========================================================================
- * Bootstrap: transition.js v3.0.3
- * http://getbootstrap.com/javascript/#transitions
- * ========================================================================
- * Copyright 2013 Twitter, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ======================================================================== */
-
-
-+function ($) { "use strict";
-
- // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
- // ============================================================
-
- function transitionEnd() {
- var el = document.createElement('bootstrap')
-
- var transEndEventNames = {
- 'WebkitTransition' : 'webkitTransitionEnd'
- , 'MozTransition' : 'transitionend'
- , 'OTransition' : 'oTransitionEnd otransitionend'
- , 'transition' : 'transitionend'
- }
-
- for (var name in transEndEventNames) {
- if (el.style[name] !== undefined) {
- return { end: transEndEventNames[name] }
- }
- }
- }
-
- // http://blog.alexmaccaw.com/css-transitions
- $.fn.emulateTransitionEnd = function (duration) {
- var called = false, $el = this
- $(this).one($.support.transition.end, function () { called = true })
- var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
- setTimeout(callback, duration)
- return this
- }
-
- $(function () {
- $.support.transition = transitionEnd()
- })
-
-}(jQuery);
diff --git a/trustie2/public/javascripts/ckeditor/CHANGES.md b/trustie2/public/javascripts/ckeditor/CHANGES.md
deleted file mode 100644
index 3a8d07963..000000000
--- a/trustie2/public/javascripts/ckeditor/CHANGES.md
+++ /dev/null
@@ -1,342 +0,0 @@
-CKEditor 4 Changelog
-====================
-
-## CKEditor 4.3
-
-New Features:
-
-* [#10612](http://dev.ckeditor.com/ticket/10612): Internet Explorer 11 support.
-* [#10869](http://dev.ckeditor.com/ticket/10869): Widgets: Added better integration with the [Elements Path](http://ckeditor.com/addon/elementspath) plugin.
-* [#10886](http://dev.ckeditor.com/ticket/10886): Widgets: Added tooltip to the drag handle.
-* [#10933](http://dev.ckeditor.com/ticket/10933): Widgets: Introduced drag and drop of block widgets with the [Line Utilities](http://ckeditor.com/addon/lineutils) plugin.
-* [#10936](http://dev.ckeditor.com/ticket/10936): Widget System changes for easier integration with other dialog systems.
-* [#10895](http://dev.ckeditor.com/ticket/10895): [Enhanced Image](http://ckeditor.com/addon/image2): Added file browser integration.
-* [#11002](http://dev.ckeditor.com/ticket/11002): Added the [`draggable`](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget.definition-property-draggable) option to disable drag and drop support for widgets.
-* [#10937](http://dev.ckeditor.com/ticket/10937): [Mathematical Formulas](http://ckeditor.com/addon/mathjax) widget improvements:
- * loading indicator ([#10948](http://dev.ckeditor.com/ticket/10948)),
- * applying paragraph changes (like font color change) to iframe ([#10841](http://dev.ckeditor.com/ticket/10841)),
- * Firefox and IE9 clipboard fixes ([#10857](http://dev.ckeditor.com/ticket/10857)),
- * fixing same origin policy issue ([#10840](http://dev.ckeditor.com/ticket/10840)),
- * fixing undo bugs ([#10842](http://dev.ckeditor.com/ticket/10842), [#10930](http://dev.ckeditor.com/ticket/10930)),
- * fixing other minor bugs.
-* [#10862](http://dev.ckeditor.com/ticket/10862): [Placeholder](http://ckeditor.com/addon/placeholder) plugin was rewritten as a widget.
-* [#10822](http://dev.ckeditor.com/ticket/10822): Added styles system integration with non-editable elements (for example widgets) and their nested editables. Styles cannot change non-editable content and are applied in nested editable only if allowed by its type and content filter.
-* [#10856](http://dev.ckeditor.com/ticket/10856): Menu buttons will now toggle the visibility of their panels when clicked multiple times. [Language](http://ckeditor.com/addon/language) plugin fixes: Added active language highlighting, added an option to remove the language.
-* [#10028](http://dev.ckeditor.com/ticket/10028): New [`config.dialog_noConfirmCancel`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-dialog_noConfirmCancel) configuration option that eliminates the need to confirm closing of a dialog window when the user changed any of its fields.
-* [#10848](http://dev.ckeditor.com/ticket/10848): Integrate remaining plugins ([Styles](http://ckeditor.com/addon/stylescombo), [Format](http://ckeditor.com/addon/format), [Font](http://ckeditor.com/addon/font), [Color Button](http://ckeditor.com/addon/colorbutton), [Language](http://ckeditor.com/addon/language) and [Indent](http://ckeditor.com/addon/indent)) with [active filter](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-activeFilter).
-* [#10855](http://dev.ckeditor.com/ticket/10855): Change the extension of emoticons in the [BBCode](http://ckeditor.com/addon/bbcode) sample from GIF to PNG.
-
-Fixed Issues:
-
-* [#10831](http://dev.ckeditor.com/ticket/10831): [Enhanced Image](http://ckeditor.com/addon/image2): Merged `image2inline` and `image2block` into one `image2` widget.
-* [#10835](http://dev.ckeditor.com/ticket/10835): [Enhanced Image](http://ckeditor.com/addon/image2): Improved visibility of the resize handle.
-* [#10836](http://dev.ckeditor.com/ticket/10836): [Enhanced Image](http://ckeditor.com/addon/image2): Preserve custom mouse cursor while resizing the image.
-* [#10939](http://dev.ckeditor.com/ticket/10939): [Firefox] [Enhanced Image](http://ckeditor.com/addon/image2): hovering the image causes it to change.
-* [#10866](http://dev.ckeditor.com/ticket/10866): Fixed: Broken *Tab* key navigation in the [Enhanced Image](http://ckeditor.com/addon/image2) dialog window.
-* [#10833](http://dev.ckeditor.com/ticket/10833): Fixed: *Lock ratio* option should be on by default in the [Enhanced Image](http://ckeditor.com/addon/image2) dialog window.
-* [#10881](http://dev.ckeditor.com/ticket/10881): Various improvements to *Enter* key behavior in nested editables.
-* [#10879](http://dev.ckeditor.com/ticket/10879): [Remove Format](http://ckeditor.com/addon/removeformat) should not leak from a nested editable.
-* [#10877](http://dev.ckeditor.com/ticket/10877): Fixed: [WebSpellChecker](http://ckeditor.com/addon/wsc) fails to apply changes if a nested editable was focused.
-* [#10877](http://dev.ckeditor.com/ticket/10877): Fixed: [SCAYT](http://ckeditor.com/addon/wsc) blocks typing in nested editables.
-* [#11079](http://dev.ckeditor.com/ticket/11079): Add button icons to the [Placeholder](http://ckeditor.com/addon/placeholder) sample.
-* [#10870](http://dev.ckeditor.com/ticket/10870): The `paste` command is no longer being disabled when the clipboard is empty.
-* [#10854](http://dev.ckeditor.com/ticket/10854): Fixed: Firefox prepends `
` to ``, so it is stripped by the HTML data processor.
-* [#10823](http://dev.ckeditor.com/ticket/10823): Fixed: [Link](http://ckeditor.com/addon/link) plugin does not work with non-editable content.
-* [#10828](http://dev.ckeditor.com/ticket/10828): [Magic Line](http://ckeditor.com/addon/magicline) integration with the Widget System.
-* [#10865](http://dev.ckeditor.com/ticket/10865): Improved hiding copybin, so copying widgets works smoothly.
-* [#11066](http://dev.ckeditor.com/ticket/11066): Widget's private parts use CSS reset.
-* [#11027](http://dev.ckeditor.com/ticket/11027): Fixed: Block commands break on widgets; added the [`contentDomInvalidated`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-contentDomInvalidated) event.
-* [#10430](http://dev.ckeditor.com/ticket/10430): Resolve dependence of the [Image](http://ckeditor.com/addon/image) plugin on the [Form Elements](http://ckeditor.com/addon/forms) plugin.
-* [#10911](http://dev.ckeditor.com/ticket/10911): Fixed: Browser *Alt* hotkeys will no longer be blocked while a widget is focused.
-* [#11082](http://dev.ckeditor.com/ticket/11082): Fixed: Selected widget is not copied or cut when using toolbar buttons or context menu.
-* [#11083](http://dev.ckeditor.com/ticket/11083): Fixed list and div element application to block widgets.
-* [#10887](http://dev.ckeditor.com/ticket/10887): Internet Explorer 8 compatibility issues related to the Widget System.
-* [#11074](http://dev.ckeditor.com/ticket/11074): Temporarily disabled inline widget drag and drop, because of seriously buggy native `range#moveToPoint` method.
-* [#11098](http://dev.ckeditor.com/ticket/11098): Fixed: Wrong selection position after undoing widget drag and drop.
-* [#11110](http://dev.ckeditor.com/ticket/11110): Fixed: IFrame and Flash objects are being incorrectly pasted in certain conditions.
-* [#11129](http://dev.ckeditor.com/ticket/11129): Page break is lost when loading data.
-* [#11123](http://dev.ckeditor.com/ticket/11123): [Firefox] Widget is destroyed after being dragged outside of ``.
-* [#11124](http://dev.ckeditor.com/ticket/11124): Fixed the [Elements Path](http://ckeditor.com/addon/elementspath) in an editor using the [Div Editing Area](http://ckeditor.com/addon/divarea).
-
-## CKEditor 4.3 Beta
-
-New Features:
-
-* [#9764](http://dev.ckeditor.com/ticket/9764): Widget System.
- * [Widget plugin](http://ckeditor.com/addon/widget) introducing the [Widget API](http://docs.ckeditor.com/#!/api/CKEDITOR.plugins.widget).
- * New [`editor.enterMode`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-enterMode) and [`editor.shiftEnterMode`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-shiftEnterMode) properties – normalized versions of [`config.enterMode`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-enterMode) and [`config.shiftEnterMode`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-shiftEnterMode).
- * Dynamic editor settings. Starting from CKEditor 4.3 Beta, *Enter* mode values and [content filter](http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter) instances may be changed dynamically (for example when the caret was placed in an element in which editor features should be adjusted). When you are implementing a new editor feature, you should base its behavior on [dynamic](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-activeEnterMode) or [static](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-enterMode) *Enter* mode values depending on whether this feature works in selection context or globally on editor content.
- * Dynamic *Enter* mode values – [`editor.setActiveEnterMode`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-setActiveEnterMode) method, [`editor.activeEnterModeChange`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-activeEnterModeChange) event, and two properties: [`editor.activeEnterMode`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-activeEnterMode) and [`editor.activeShiftEnterMode`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-activeShiftEnterMode).
- * Dynamic content filter instances – [`editor.setActiveFilter`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-method-setActiveFilter) method, [`editor.activeFilterChange`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-activeFilterChange) event, and [`editor.activeFilter`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-property-activeFilter) property.
- * "Fake" selection was introduced. It makes it possible to virtually select any element when the real selection remains hidden. See the [`selection.fake`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.selection-method-fake) method.
- * Default [`htmlParser.filter`](http://docs.ckeditor.com/#!/api/CKEDITOR.htmlParser.filter) rules are not applied to non-editable elements (elements with `contenteditable` attribute set to `false` and their descendants) anymore. To add a rule which will be applied to all elements you need to pass an additional argument to the [`filter.addRules`](http://docs.ckeditor.com/#!/api/CKEDITOR.htmlParser.filter-method-addRules) method.
- * Dozens of new methods were introduced – most interesting ones:
- * [`document.find`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.document-method-find),
- * [`document.findOne`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.document-method-findOne),
- * [`editable.insertElementIntoRange`](http://docs.ckeditor.com/#!/api/CKEDITOR.editable-method-insertElementIntoRange),
- * [`range.moveToClosestEditablePosition`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.range-method-moveToClosestEditablePosition),
- * New methods for [`htmlParser.node`](http://docs.ckeditor.com/#!/api/CKEDITOR.htmlParser.node) and [`htmlParser.element`](http://docs.ckeditor.com/#!/api/CKEDITOR.htmlParser.element).
-* [#10659](http://dev.ckeditor.com/ticket/10659): New [Enhanced Image](http://ckeditor.com/addon/image2) plugin that introduces a widget with integrated image captions, an option to center images, and dynamic "click and drag" resizing.
-* [#10664](http://dev.ckeditor.com/ticket/10664): New [Mathematical Formulas](http://ckeditor.com/addon/mathjax) plugin that introduces the MathJax widget.
-* [#7987](https://dev.ckeditor.com/ticket/7987): New [Language](http://ckeditor.com/addon/language) plugin that implements Language toolbar button to support [WCAG 3.1.2 Language of Parts](http://www.w3.org/TR/UNDERSTANDING-WCAG20/meaning-other-lang-id.html).
-* [#10708](http://dev.ckeditor.com/ticket/10708): New [smileys](http://ckeditor.com/addon/smiley).
-
-## CKEditor 4.2.3
-
-Fixed Issues:
-
-* [#10994](http://dev.ckeditor.com/ticket/10994): Fixed: Loading external jQuery library when opening the [jQuery Adapter](http://docs.ckeditor.com/#!/guide/dev_jquery) sample directly from file.
-* [#10975](http://dev.ckeditor.com/ticket/10975): [IE] Fixed: Error thrown while opening the color palette.
-* [#9929](http://dev.ckeditor.com/ticket/9929): [Blink/WebKit] Fixed: A non-breaking space is created once a character is deleted and a regular space is typed.
-* [#10963](http://dev.ckeditor.com/ticket/10963): Fixed: JAWS issue with the keyboard shortcut for [Magic Line](http://ckeditor.com/addon/magicline).
-* [#11096](http://dev.ckeditor.com/ticket/11096): Fixed: TypeError: Object has no method 'is'.
-
-## CKEditor 4.2.2
-
-Fixed Issues:
-
-* [#9314](http://dev.ckeditor.com/ticket/9314): Fixed: Incorrect error message on closing a dialog window without saving changs.
-* [#10308](http://dev.ckeditor.com/ticket/10308): [IE10] Fixed: Unspecified error when deleting a row.
-* [#10945](http://dev.ckeditor.com/ticket/10945): [Chrome] Fixed: Clicking with a mouse inside the editor does not show the caret.
-* [#10912](http://dev.ckeditor.com/ticket/10912): Prevent default action when content of a non-editable link is clicked.
-* [#10913](http://dev.ckeditor.com/ticket/10913): Fixed [`CKEDITOR.plugins.addExternal`](http://docs.ckeditor.com/#!/api/CKEDITOR.resourceManager-method-addExternal) not handling paths including file name specified.
-* [#10666](http://dev.ckeditor.com/ticket/10666): Fixed [`CKEDITOR.tools.isArray`](http://docs.ckeditor.com/#!/api/CKEDITOR.tools-method-isArray) not working cross frame.
-* [#10910](http://dev.ckeditor.com/ticket/10910): [IE9] Fixed JavaScript error thrown in Compatibility Mode when clicking and/or typing in the editing area.
-* [#10868](http://dev.ckeditor.com/ticket/10868): [IE8] Prevent the browser from crashing when applying the Inline Quotation style.
-* [#10915](http://dev.ckeditor.com/ticket/10915): Fixed: Invalid CSS filter in the Kama skin.
-* [#10914](http://dev.ckeditor.com/ticket/10914): Plugins [Indent List](http://ckeditor.com/addon/indentlist) and [Indent Block](http://ckeditor.com/addon/indentblock) are now included in the build configuration.
-* [#10812](http://dev.ckeditor.com/ticket/10812): Fixed [`range#createBookmark2`](http://docs.ckeditor.com/#!/api/CKEDITOR.dom.range-method-createBookmark2) incorrectly normalizing offsets. This bug was causing many issues: [#10850](http://dev.ckeditor.com/ticket/10850), [#10842](http://dev.ckeditor.com/ticket/10842).
-* [#10951](http://dev.ckeditor.com/ticket/10951): Reviewed and optimized focus handling on panels (combo, menu buttons, color buttons, and context menu) to enhance accessibility. Fixed [#10705](http://dev.ckeditor.com/ticket/10705), [#10706](http://dev.ckeditor.com/ticket/10706) and [#10707](http://dev.ckeditor.com/ticket/10707).
-* [#10704](http://dev.ckeditor.com/ticket/10704): Fixed a JAWS issue with the Select Color dialog window title not being announced.
-* [#10753](http://dev.ckeditor.com/ticket/10753): The floating toolbar in inline instances now has a dedicated accessibility label.
-
-## CKEditor 4.2.1
-
-Fixed Issues:
-
-* [#10301](http://dev.ckeditor.com/ticket/10301): [IE9-10] Undo fails after 3+ consecutive paste actions with a JavaScript error.
-* [#10689](http://dev.ckeditor.com/ticket/10689): Save toolbar button saves only the first editor instance.
-* [#10368](http://dev.ckeditor.com/ticket/10368): Move language reading direction definition (`dir`) from main language file to core.
-* [#9330](http://dev.ckeditor.com/ticket/9330): Fixed pasting anchors from MS Word.
-* [#8103](http://dev.ckeditor.com/ticket/8103): Fixed pasting nested lists from MS Word.
-* [#9958](http://dev.ckeditor.com/ticket/9958): [IE9] Pressing the "OK" button will trigger the `onbeforeunload` event in the popup dialog.
-* [#10662](http://dev.ckeditor.com/ticket/10662): Fixed styles from the Styles drop-down list not registering to the ACF in case when the [Shared Spaces plugin](http://ckeditor.com/addon/sharedspace) is used.
-* [#9654](http://dev.ckeditor.com/ticket/9654): Problems with Internet Explorer 10 Quirks Mode.
-* [#9816](http://dev.ckeditor.com/ticket/9816): Floating toolbar does not reposition vertically in several cases.
-* [#10646](http://dev.ckeditor.com/ticket/10646): Removing a selected sublist or nested table with *Backspace/Delete* removes the parent element.
-* [#10623](http://dev.ckeditor.com/ticket/10623): [WebKit] Page is scrolled when opening a drop-down list.
-* [#10004](http://dev.ckeditor.com/ticket/10004): [ChromeVox] Button names are not announced.
-* [#10731](http://dev.ckeditor.com/ticket/10731): [WebSpellChecker](http://ckeditor.com/addon/wsc) plugin breaks cloning of editor configuration.
-* It is now possible to set per instance [WebSpellChecker](http://ckeditor.com/addon/wsc) plugin configuration instead of setting the configuration globally.
-
-## CKEditor 4.2
-
-**Important Notes:**
-
-* Dropped compatibility support for Internet Explorer 7 and Firefox 3.6.
-
-* Both the Basic and the Standard distribution packages will not contain the new [Indent Block](http://ckeditor.com/addon/indentblock) plugin. Because of this the [Advanced Content Filter](http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter) might remove block indentations from existing contents. If you want to prevent this, either [add an appropriate ACF rule to your filter](http://docs.ckeditor.com/#!/guide/dev_allowed_content_rules) or create a custom build based on the Basic/Standard package and add the Indent Block plugin in [CKBuilder](http://ckeditor.com/builder).
-
-New Features:
-
-* [#10027](http://dev.ckeditor.com/ticket/10027): Separated list and block indentation into two plugins: [Indent List](http://ckeditor.com/addon/indentlist) and [Indent Block](http://ckeditor.com/addon/indentblock).
-* [#8244](http://dev.ckeditor.com/ticket/8244): Use *(Shift+)Tab* to indent and outdent lists.
-* [#10281](http://dev.ckeditor.com/ticket/10281): The [jQuery Adapter](http://docs.ckeditor.com/#!/guide/dev_jquery) is now available. Several jQuery-related issues fixed: [#8261](http://dev.ckeditor.com/ticket/8261), [#9077](http://dev.ckeditor.com/ticket/9077), [#8710](http://dev.ckeditor.com/ticket/8710), [#8530](http://dev.ckeditor.com/ticket/8530), [#9019](http://dev.ckeditor.com/ticket/9019), [#6181](http://dev.ckeditor.com/ticket/6181), [#7876](http://dev.ckeditor.com/ticket/7876), [#6906](http://dev.ckeditor.com/ticket/6906).
-* [#10042](http://dev.ckeditor.com/ticket/10042): Introduced [`config.title`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-title) setting to change the human-readable title of the editor.
-* [#9794](http://dev.ckeditor.com/ticket/9794): Added [`editor.onChange`](http://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-change) event.
-* [#9923](http://dev.ckeditor.com/ticket/9923): HiDPI support in the editor UI. HiDPI icons for [Moono skin](http://ckeditor.com/addon/moono) added.
-* [#8031](http://dev.ckeditor.com/ticket/8031): Handle `required` attributes on ` {series.name}
Maximum: {point.high}
Upper quartile: {point.q3}
Median: {point.median}
Lower quartile: {point.q1}
Minimum: {point.low}
'},whiskerLength:"50%",whiskerWidth:2});h.boxplot=v(h.column,{type:"boxplot",pointArrayMap:["low","q1",
-"median","q3","high"],toYData:function(a){return[a.low,a.q1,a.median,a.q3,a.high]},pointValKey:"high",pointAttrToOptions:{fill:"fillColor",stroke:"color","stroke-width":"lineWidth"},drawDataLabels:r,translate:function(){var a=this.yAxis,b=this.pointArrayMap;h.column.prototype.translate.apply(this);t(this.points,function(c){t(b,function(b){c[b]!==null&&(c[b+"Plot"]=a.translate(c[b],0,1,0,1))})})},drawPoints:function(){var a=this,b=a.points,c=a.options,d=a.chart.renderer,e,f,i,g,l,m,j,n,h,A,k,J,p,o,
-u,r,v,s,w,x,z,y,F=a.doQuartiles!==!1,C=parseInt(a.options.whiskerLength,10)/100;t(b,function(b){h=b.graphic;z=b.shapeArgs;k={};o={};r={};y=b.color||a.color;if(b.plotY!==D)if(e=b.pointAttr[b.selected?"selected":""],v=z.width,s=B(z.x),w=s+v,x=E(v/2),f=B(F?b.q1Plot:b.lowPlot),i=B(F?b.q3Plot:b.lowPlot),g=B(b.highPlot),l=B(b.lowPlot),k.stroke=b.stemColor||c.stemColor||y,k["stroke-width"]=q(b.stemWidth,c.stemWidth,c.lineWidth),k.dashstyle=b.stemDashStyle||c.stemDashStyle,o.stroke=b.whiskerColor||c.whiskerColor||
-y,o["stroke-width"]=q(b.whiskerWidth,c.whiskerWidth,c.lineWidth),r.stroke=b.medianColor||c.medianColor||y,r["stroke-width"]=q(b.medianWidth,c.medianWidth,c.lineWidth),j=k["stroke-width"]%2/2,n=s+x+j,A=["M",n,i,"L",n,g,"M",n,f,"L",n,l],F&&(j=e["stroke-width"]%2/2,n=B(n)+j,f=B(f)+j,i=B(i)+j,s+=j,w+=j,J=["M",s,i,"L",s,f,"L",w,f,"L",w,i,"L",s,i,"z"]),C&&(j=o["stroke-width"]%2/2,g+=j,l+=j,p=["M",n-x*C,g,"L",n+x*C,g,"M",n-x*C,l,"L",n+x*C,l]),j=r["stroke-width"]%2/2,m=E(b.medianPlot)+j,u=["M",s,m,"L",w,
-m],h)b.stem.animate({d:A}),C&&b.whiskers.animate({d:p}),F&&b.box.animate({d:J}),b.medianShape.animate({d:u});else{b.graphic=h=d.g().add(a.group);b.stem=d.path(A).attr(k).add(h);if(C)b.whiskers=d.path(p).attr(o).add(h);if(F)b.box=d.path(J).attr(e).add(h);b.medianShape=d.path(u).attr(r).add(h)}})},setStackedPoints:r});p.errorbar=o(p.boxplot,{color:"#000000",grouping:!1,linkedTo:":previous",tooltip:{pointFormat:'\u25CF {series.name}: {point.low} - {point.high}
'},
-whiskerWidth:null});h.errorbar=v(h.boxplot,{type:"errorbar",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"high",doQuartiles:!1,drawDataLabels:h.arearange?h.arearange.prototype.drawDataLabels:r,getColumnMetrics:function(){return this.linkedParent&&this.linkedParent.columnMetrics||h.column.prototype.getColumnMetrics.call(this)}});p.waterfall=o(p.column,{lineWidth:1,lineColor:"#333",dashStyle:"dot",borderColor:"#333",dataLabels:{inside:!0},states:{hover:{lineWidthPlus:0}}});
-h.waterfall=v(h.column,{type:"waterfall",upColorProp:"fill",pointValKey:"y",translate:function(){var a=this.options,b=this.yAxis,c,d,e,f,i,g,l,m,j,n=a.threshold,k=a.stacking;h.column.prototype.translate.apply(this);l=m=n;d=this.points;for(c=0,a=d.length;c0?b.translate(l,0,1)-f.y:b.translate(l,0,1)-b.translate(l-g,0,1);l+=g}f.height<0&&(f.y+=f.height,f.height*=-1);e.plotY=f.y=E(f.y)-this.borderWidth%2/2;f.height=N(E(f.height),0.001);e.yBottom=f.y+f.height;f=e.plotY+(e.negative?f.height:0);this.chart.inverted?e.tooltipPos[0]=b.len-
-f:e.tooltipPos[1]=f}},processData:function(a){var b=this.yData,c=this.options.data,d,e=b.length,f,i,g,l,m,j;i=f=g=l=this.options.threshold||0;for(j=0;j0?(b.pointAttr=e,b.color=d):b.pointAttr=a.pointAttr})},getGraphPath:function(){var a=this.data,b=a.length,c=E(this.options.lineWidth+this.borderWidth)%2/2,d=[],e,f,i;for(i=1;i0?(g[f]-a)/(b-a):0.5,m&&i>=0&&(i=Math.sqrt(i)),l.push(w.ceil(c+i*(d-c))/2);this.radii=l},animate:function(a){var b=this.options.animation;if(!a)t(this.points,function(a){var d=a.graphic,a=a.shapeArgs;d&&a&&(d.attr("r",1),d.animate({r:a.r},b))}),this.animate=null},translate:function(){var a,b=this.data,c,d,e=this.radii;h.scatter.prototype.translate.call(this);for(a=b.length;a--;)c=b[a],d=e?e[a]:0,d>=this.minPxSize/2?(c.shapeType="circle",c.shapeArgs={x:c.plotX,y:c.plotY,r:d},c.dlBox=
-{x:c.plotX-d,y:c.plotY-d,width:2*d,height:2*d}):c.shapeArgs=c.plotY=c.dlBox=D},drawLegendSymbol:function(a,b){var c=x(a.itemStyle.fontSize)/2;b.legendSymbol=this.chart.renderer.circle(c,a.baseline-c,c).attr({zIndex:3}).add(b.legendGroup);b.legendSymbol.isMarker=!0},drawPoints:h.column.prototype.drawPoints,alignDataLabel:h.column.prototype.alignDataLabel,buildKDTree:r,applyZones:r});M.prototype.beforePadding=function(){var a=this,b=this.len,c=this.chart,d=0,e=b,f=this.isXAxis,i=f?"xData":"yData",g=
-this.min,l={},m=w.min(c.plotWidth,c.plotHeight),j=Number.MAX_VALUE,n=-Number.MAX_VALUE,h=this.max-g,k=b/h,p=[];t(this.series,function(b){var g=b.options;if(b.bubblePadding&&(b.visible||!c.options.chart.ignoreHiddenSeries))if(a.allowZoomOutside=!0,p.push(b),f)t(["minSize","maxSize"],function(a){var b=g[a],f=/%$/.test(b),b=x(b);l[a]=f?m*b/100:b}),b.minPxSize=l.minSize,b=b.zData,b.length&&(j=q(g.zMin,w.min(j,w.max(P(b),g.displayNegative===!1?g.zThreshold:-Number.MAX_VALUE))),n=q(g.zMax,w.max(n,Q(b))))});
-t(p,function(a){var b=a[i],c=b.length,m;f&&a.getRadii(j,n,l.minSize,l.maxSize);if(h>0)for(;c--;)typeof b[c]==="number"&&(m=a.radii[c],d=Math.min((b[c]-g)*k-m,d),e=Math.max((b[c]-g)*k+m,e))});p.length&&h>0&&q(this.options.min,this.userMin)===D&&q(this.options.max,this.userMax)===D&&(e-=b,k*=(b+d-e)/b,this.min+=d/k,this.max+=e/k)};(function(){function a(a,b,c){a.call(this,b,c);if(this.chart.polar)this.closeSegment=function(a){var b=this.xAxis.center;a.push("L",b[0],b[1])},this.closedStacks=!0}function b(a,
-b){var c=this.chart,d=this.options.animation,e=this.group,j=this.markerGroup,n=this.xAxis.center,h=c.plotLeft,k=c.plotTop;if(c.polar){if(c.renderer.isSVG)d===!0&&(d={}),b?(c={translateX:n[0]+h,translateY:n[1]+k,scaleX:0.001,scaleY:0.001},e.attr(c),j&&j.attr(c)):(c={translateX:h,translateY:k,scaleX:1,scaleY:1},e.animate(c,d),j&&j.animate(c,d),this.animate=null)}else a.call(this,b)}var c=s.prototype,d=S.prototype,e;c.searchPointByAngle=function(a){var b=this.chart,c=this.xAxis.pane.center;return this.searchKDTree({clientX:180+
-Math.atan2(a.chartX-c[0]-b.plotLeft,a.chartY-c[1]-b.plotTop)*(-180/Math.PI)})};u(c,"buildKDTree",function(a){if(this.chart.polar)this.kdByAngle?this.searchPoint=this.searchPointByAngle:this.kdDimensions=2;a.apply(this)});c.toXY=function(a){var b,c=this.chart,d=a.plotX;b=a.plotY;a.rectPlotX=d;a.rectPlotY=b;b=this.xAxis.postTranslate(a.plotX,this.yAxis.len-b);a.plotX=a.polarPlotX=b.x-c.plotLeft;a.plotY=a.polarPlotY=b.y-c.plotTop;this.kdByAngle?(c=(d/Math.PI*180+this.xAxis.pane.options.startAngle)%360,
-c<0&&(c+=360),a.clientX=c):a.clientX=a.plotX};h.area&&u(h.area.prototype,"init",a);h.areaspline&&u(h.areaspline.prototype,"init",a);h.spline&&u(h.spline.prototype,"getPointSpline",function(a,b,c,d){var e,j,n,h,k,p,o;if(this.chart.polar){e=c.plotX;j=c.plotY;a=b[d-1];n=b[d+1];this.connectEnds&&(a||(a=b[b.length-2]),n||(n=b[1]));if(a&&n)h=a.plotX,k=a.plotY,b=n.plotX,p=n.plotY,h=(1.5*e+h)/2.5,k=(1.5*j+k)/2.5,n=(1.5*e+b)/2.5,o=(1.5*j+p)/2.5,b=Math.sqrt(Math.pow(h-e,2)+Math.pow(k-j,2)),p=Math.sqrt(Math.pow(n-
-e,2)+Math.pow(o-j,2)),h=Math.atan2(k-j,h-e),k=Math.atan2(o-j,n-e),o=Math.PI/2+(h+k)/2,Math.abs(h-o)>Math.PI/2&&(o-=Math.PI),h=e+Math.cos(o)*b,k=j+Math.sin(o)*b,n=e+Math.cos(Math.PI+o)*p,o=j+Math.sin(Math.PI+o)*p,c.rightContX=n,c.rightContY=o;d?(c=["C",a.rightContX||a.plotX,a.rightContY||a.plotY,h||e,k||j,e,j],a.rightContX=a.rightContY=null):c=["M",e,j]}else c=a.call(this,b,c,d);return c});u(c,"translate",function(a){var b=this.chart;a.call(this);if(b.polar&&(this.kdByAngle=b.tooltip&&b.tooltip.shared,
-!this.preventPostTranslate)){a=this.points;for(b=a.length;b--;)this.toXY(a[b])}});u(c,"getSegmentPath",function(a,b){var c=this.points;if(this.chart.polar&&this.options.connectEnds!==!1&&b[b.length-1]===c[c.length-1]&&c[0].y!==null)this.connectEnds=!0,b=[].concat(b,[c[0]]);return a.call(this,b)});u(c,"animate",b);if(h.column)e=h.column.prototype,u(e,"animate",b),u(e,"translate",function(a){var b=this.xAxis,c=this.yAxis.len,d=b.center,e=b.startAngleRad,j=this.chart.renderer,h,k;this.preventPostTranslate=
-!0;a.call(this);if(b.isRadial){b=this.points;for(k=b.length;k--;)h=b[k],a=h.barX+e,h.shapeType="path",h.shapeArgs={d:j.symbols.arc(d[0],d[1],c-h.plotY,null,{start:a,end:a+h.pointWidth,innerR:c-q(h.yBottom,c)})},this.toXY(h),h.tooltipPos=[h.plotX,h.plotY],h.ttBelow=h.plotY>d[1]}}),u(e,"alignDataLabel",function(a,b,d,e,h,j){if(this.chart.polar){a=b.rectPlotX/Math.PI*180;if(e.align===null)e.align=a>20&&a<160?"left":a>200&&a<340?"right":"center";if(e.verticalAlign===null)e.verticalAlign=a<45||a>315?"bottom":
-a>135&&a<225?"top":"middle";c.alignDataLabel.call(this,b,d,e,h,j)}else a.call(this,b,d,e,h,j)});u(d,"getCoordinates",function(a,b){var c=this.chart,d={xAxis:[],yAxis:[]};c.polar?t(c.axes,function(a){var e=a.isXAxis,f=a.center,h=b.chartX-f[0]-c.plotLeft,f=b.chartY-f[1]-c.plotTop;d[e?"xAxis":"yAxis"].push({axis:a,value:a.translate(e?Math.PI-Math.atan2(h,f):Math.sqrt(Math.pow(h,2)+Math.pow(f,2)),!0)})}):d=a.call(this,b);return d})})()})(Highcharts);
diff --git a/trustie2/public/javascripts/highcharts.js b/trustie2/public/javascripts/highcharts.js
deleted file mode 100644
index 3e422a0fd..000000000
--- a/trustie2/public/javascripts/highcharts.js
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- Highcharts JS v4.1.7 (2015-06-26)
-
- (c) 2009-2014 Torstein Honsi
-
- License: www.highcharts.com/license
-*/
-(function(){function z(){var a,b=arguments,c,d={},e=function(a,b){var c,d;typeof a!=="object"&&(a={});for(d in b)b.hasOwnProperty(d)&&(c=b[d],a[d]=c&&typeof c==="object"&&Object.prototype.toString.call(c)!=="[object Array]"&&d!=="renderTo"&&typeof c.nodeType!=="number"?e(a[d]||{},c):b[d]);return a};b[0]===!0&&(d=b[1],b=Array.prototype.slice.call(b,2));c=b.length;for(a=0;a-1?h.thousandsSep:""))):e=Oa(f,e)}j.push(e);a=a.slice(c+1);c=(d=!d)?"}":"{"}j.push(a);return j.join("")}function pb(a){return W.pow(10,V(W.log(a)/W.LN10))}function qb(a,b,c,d,e){var f,g=a,c=p(c,1);f=a/c;b||(b=[1,2,2.5,5,10],d===!1&&(c===
-1?b=[1,2,5,10]:c<=0.1&&(b=[1/c])));for(d=0;d=a||!e&&f<=(b[d]+(b[d+1]||b[d]))/2)break;g*=c;return g}function rb(a,b){var c=a.length,d,e;for(e=0;ec&&(c=a[b]);return c}function Qa(a,b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(),
-delete a[c]}function Ra(a){fb||(fb=$(Ka));a&&fb.appendChild(a);fb.innerHTML=""}function la(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw c;K.console&&console.log(c)}function ea(a){return parseFloat(a.toPrecision(14))}function Sa(a,b){za=p(a,b.animation)}function Db(){var a=T.global,b=a.useUTC,c=b?"getUTC":"get",d=b?"setUTC":"set";Aa=a.Date||window.Date;ob=b&&a.timezoneOffset;eb=b&&a.getTimezoneOffset;gb=function(a,c,d,h,i,j){var k;b?(k=Aa.UTC.apply(0,arguments),k+=
-Wa(k)):k=(new Aa(a,c,p(d,1),p(h,0),p(i,0),p(j,0))).getTime();return k};sb=c+"Minutes";tb=c+"Hours";ub=c+"Day";Xa=c+"Date";Ya=c+"Month";Za=c+"FullYear";Eb=d+"Milliseconds";Fb=d+"Seconds";Gb=d+"Minutes";Hb=d+"Hours";vb=d+"Date";wb=d+"Month";xb=d+"FullYear"}function Q(){}function Ta(a,b,c,d){this.axis=a;this.pos=b;this.type=c||"";this.isNew=!0;!c&&!d&&this.addLabel()}function Ib(a,b,c,d,e){var f=a.chart.inverted;this.axis=a;this.isNegative=c;this.options=b;this.x=d;this.total=null;this.points={};this.stack=
-e;this.alignOptions={align:b.align||(f?c?"left":"right":"center"),verticalAlign:b.verticalAlign||(f?"middle":c?"bottom":"top"),y:p(b.y,f?4:c?14:-6),x:p(b.x,f?c?-6:6:0)};this.textAlign=b.textAlign||(f?c?"right":"left":"center")}var y,B=document,K=window,W=Math,r=W.round,V=W.floor,ta=W.ceil,u=W.max,C=W.min,O=W.abs,X=W.cos,aa=W.sin,ma=W.PI,ha=ma*2/360,Ba=navigator.userAgent,Jb=K.opera,ya=/(msie|trident)/i.test(Ba)&&!Jb,hb=B.documentMode===8,ib=/AppleWebKit/.test(Ba),La=/Firefox/.test(Ba),Kb=/(Mobile|Android|Windows Phone)/.test(Ba),
-Ca="http://www.w3.org/2000/svg",ca=!!B.createElementNS&&!!B.createElementNS(Ca,"svg").createSVGRect,Ob=La&&parseInt(Ba.split("Firefox/")[1],10)<4,fa=!ca&&!ya&&!!B.createElement("canvas").getContext,$a,ab,Lb={},yb=0,fb,T,Oa,za,zb,E,na=function(){return y},Y=[],bb=0,Ka="div",P="none",Pb=/^[0-9]+$/,jb=["plotTop","marginRight","marginBottom","plotLeft"],Qb="stroke-width",Aa,gb,ob,eb,sb,tb,ub,Xa,Ya,Za,Eb,Fb,Gb,Hb,vb,wb,xb,M={},A;A=K.Highcharts=K.Highcharts?la(16,!0):{};A.seriesTypes=M;var x=A.extend=function(a,
-b){var c;a||(a={});for(c in b)a[c]=b[c];return a},p=A.pick=function(){var a=arguments,b,c,d=a.length;for(b=0;b3?c.length%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+O(a-c).toFixed(f).slice(2):"")};zb={init:function(a,b,c){var b=b||"",d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,g,b=b.split(" "),c=[].concat(c),h,i,j=function(a){for(g=a.length;g--;)a[g]==="M"&&a.splice(g+
-1,0,a[g+1],a[g+2],a[g+1],a[g+2])};e&&(j(b),j(c));a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6));if(d<=c.length/f&&b.length===c.length)for(;d--;)c=[].concat(c).splice(0,f).concat(c);a.shift=0;if(b.length)for(a=c.length;b.length{point.key}
',pointFormat:'\u25CF {series.name}: {point.y}
',
-shadow:!0,snap:Kb?25:10,style:{color:"#333333",cursor:"default",fontSize:"12px",padding:"8px",whiteSpace:"nowrap"}},credits:{enabled:!0,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"9px"}}};var ba=T.plotOptions,U=ba.line;Db();var Ub=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/,Vb=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
-Wb=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/,oa=function(a){var b=[],c,d;(function(a){a&&a.stops?d=Ua(a.stops,function(a){return oa(a[1])}):(c=Ub.exec(a))?b=[D(c[1]),D(c[2]),D(c[3]),parseFloat(c[4],10)]:(c=Vb.exec(a))?b=[D(c[1],16),D(c[2],16),D(c[3],16),1]:(c=Wb.exec(a))&&(b=[D(c[1]),D(c[2]),D(c[3]),1])})(a);return{get:function(c){var f;d?(f=z(a),f.stops=[].concat(f.stops),o(d,function(a,b){f.stops[b]=[f.stops[b][0],a.get(c)]})):f=b&&!isNaN(b[0])?c==="rgb"?"rgb("+b[0]+","+
-b[1]+","+b[2]+")":c==="a"?b[3]:"rgba("+b.join(",")+")":a;return f},brighten:function(a){if(d)o(d,function(b){b.brighten(a)});else if(ra(a)&&a!==0){var c;for(c=0;c<3;c++)b[c]+=D(a*255),b[c]<0&&(b[c]=0),b[c]>255&&(b[c]=255)}return this},rgba:b,setOpacity:function(a){b[3]=a;return this},raw:a}};Q.prototype={opacity:1,textProps:"fontSize,fontWeight,fontFamily,fontStyle,color,lineHeight,width,textDecoration,textShadow".split(","),init:function(a,b){this.element=b==="span"?$(b):B.createElementNS(Ca,b);
-this.renderer=a},animate:function(a,b,c){b=p(b,za,!0);db(this);if(b){b=z(b,{});if(c)b.complete=c;mb(this,a,b)}else this.attr(a),c&&c();return this},colorGradient:function(a,b,c){var d=this.renderer,e,f,g,h,i,j,k,l,m,n,v=[];a.linearGradient?f="linearGradient":a.radialGradient&&(f="radialGradient");if(f){g=a[f];h=d.gradients;j=a.stops;m=c.radialReference;Ha(g)&&(a[f]=g={x1:g[0],y1:g[1],x2:g[2],y2:g[3],gradientUnits:"userSpaceOnUse"});f==="radialGradient"&&m&&!q(g.gradientUnits)&&(g=z(g,{cx:m[0]-m[2]/
-2+g.cx*m[2],cy:m[1]-m[2]/2+g.cy*m[2],r:g.r*m[2],gradientUnits:"userSpaceOnUse"}));for(n in g)n!=="id"&&v.push(n,g[n]);for(n in j)v.push(j[n]);v=v.join(",");h[v]?a=h[v].attr("id"):(g.id=a="highcharts-"+yb++,h[v]=i=d.createElement(f).attr(g).add(d.defs),i.stops=[],o(j,function(a){a[1].indexOf("rgba")===0?(e=oa(a[1]),k=e.get("rgb"),l=e.get("a")):(k=a[1],l=1);a=d.createElement("stop").attr({offset:a[0],"stop-color":k,"stop-opacity":l}).add(i);i.stops.push(a)}));c.setAttribute(b,"url("+d.url+"#"+a+")")}},
-applyTextShadow:function(a){var b=this.element,c,d=a.indexOf("contrast")!==-1,e={},f=this.renderer.forExport||b.style.textShadow!==y&&!ya;if(d)e.textShadow=a=a.replace(/contrast/g,this.renderer.getContrast(b.style.fill));if(ib)e.textRendering="geometricPrecision";f?L(b,e):(this.fakeTS=!0,this.ySetter=this.xSetter,c=[].slice.call(b.getElementsByTagName("tspan")),o(a.split(/\s?,\s?/g),function(a){var d=b.firstChild,e,f,a=a.split(" ");e=a[a.length-1];(f=a[a.length-2])&&o(c,function(a,c){var g;c===0&&
-(a.setAttribute("x",b.getAttribute("x")),c=b.getAttribute("y"),a.setAttribute("y",c||0),c===null&&b.setAttribute("y",0));g=a.cloneNode(1);J(g,{"class":"highcharts-text-shadow",fill:e,stroke:e,"stroke-opacity":1/u(D(f),3),"stroke-width":f,"stroke-linejoin":"round"});b.insertBefore(g,d)})}))},attr:function(a,b){var c,d,e=this.element,f,g=this,h;typeof a==="string"&&b!==y&&(c=a,a={},a[c]=b);if(typeof a==="string")g=(this[a+"Getter"]||this._defaultGetter).call(this,a,e);else{for(c in a){d=a[c];h=!1;this.symbolName&&
-/^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(c)&&(f||(this.symbolAttr(a),f=!0),h=!0);if(this.rotation&&(c==="x"||c==="y"))this.doTransform=!0;h||(this[c+"Setter"]||this._defaultSetter).call(this,d,c,e);this.shadows&&/^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(c)&&this.updateShadows(c,d)}if(this.doTransform)this.updateTransform(),this.doTransform=!1}return g},updateShadows:function(a,b){for(var c=this.shadows,d=c.length;d--;)c[d].setAttribute(a,a==="height"?u(b-(c[d].cutHeight||
-0),0):a==="d"?this.d:b)},addClass:function(a){var b=this.element,c=J(b,"class")||"";c.indexOf(a)===-1&&J(b,"class",c+" "+a);return this},symbolAttr:function(a){var b=this;o("x,y,r,start,end,width,height,innerR,anchorX,anchorY".split(","),function(c){b[c]=p(a[c],b[c])});b.attr({d:b.renderer.symbols[b.symbolName](b.x,b.y,b.width,b.height,b)})},clip:function(a){return this.attr("clip-path",a?"url("+this.renderer.url+"#"+a.id+")":P)},crisp:function(a){var b,c={},d,e=a.strokeWidth||this.strokeWidth||0;
-d=r(e)%2/2;a.x=V(a.x||this.x||0)+d;a.y=V(a.y||this.y||0)+d;a.width=V((a.width||this.width||0)-2*d);a.height=V((a.height||this.height||0)-2*d);a.strokeWidth=e;for(b in a)this[b]!==a[b]&&(this[b]=c[b]=a[b]);return c},css:function(a){var b=this.styles,c={},d=this.element,e,f,g="";e=!b;if(a&&a.color)a.fill=a.color;if(b)for(f in a)a[f]!==b[f]&&(c[f]=a[f],e=!0);if(e){e=this.textWidth=a&&a.width&&d.nodeName.toLowerCase()==="text"&&D(a.width)||this.textWidth;b&&(a=x(b,c));this.styles=a;e&&(fa||!ca&&this.renderer.forExport)&&
-delete a.width;if(ya&&!ca)L(this.element,a);else{b=function(a,b){return"-"+b.toLowerCase()};for(f in a)g+=f.replace(/([A-Z])/g,b)+":"+a[f]+";";J(d,"style",g)}e&&this.added&&this.renderer.buildText(this)}return this},on:function(a,b){var c=this,d=c.element;ab&&a==="click"?(d.ontouchstart=function(a){c.touchEventFired=Aa.now();a.preventDefault();b.call(d,a)},d.onclick=function(a){(Ba.indexOf("Android")===-1||Aa.now()-(c.touchEventFired||0)>1100)&&b.call(d,a)}):d["on"+a]=b;return this},setRadialReference:function(a){this.element.radialReference=
-a;return this},translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){this.inverted=!0;this.updateTransform();return this},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.scaleX,d=this.scaleY,e=this.inverted,f=this.rotation,g=this.element;e&&(a+=this.attr("width"),b+=this.attr("height"));a=["translate("+a+","+b+")"];e?a.push("rotate(90) scale(-1,1)"):f&&a.push("rotate("+f+" "+(g.getAttribute("x")||0)+" "+(g.getAttribute("y")||0)+")");
-(q(c)||q(d))&&a.push("scale("+p(c,1)+" "+p(d,1)+")");a.length&&g.setAttribute("transform",a.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){var d,e,f,g,h={};e=this.renderer;f=e.alignedObjects;if(a){if(this.alignOptions=a,this.alignByTranslate=b,!c||Da(c))this.alignTo=d=c||"renderer",ja(f,this),f.push(this),c=null}else a=this.alignOptions,b=this.alignByTranslate,d=this.alignTo;c=p(c,e[d],e);d=a.align;e=a.verticalAlign;f=(c.x||0)+(a.x||
-0);g=(c.y||0)+(a.y||0);if(d==="right"||d==="center")f+=(c.width-(a.width||0))/{right:1,center:2}[d];h[b?"translateX":"x"]=r(f);if(e==="bottom"||e==="middle")g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);h[b?"translateY":"y"]=r(g);this[this.placed?"animate":"attr"](h);this.placed=!0;this.alignAttr=h;return this},getBBox:function(a){var b,c=this.renderer,d,e=this.rotation,f=this.element,g=this.styles,h=e*ha;d=this.textStr;var i,j=f.style,k,l;d!==y&&(l=["",e||0,g&&g.fontSize,f.style.width].join(","),
-l=d===""||Pb.test(d)?"num:"+d.toString().length+l:d+l);l&&!a&&(b=c.cache[l]);if(!b){if(f.namespaceURI===Ca||c.forExport){try{k=this.fakeTS&&function(a){o(f.querySelectorAll(".highcharts-text-shadow"),function(b){b.style.display=a})},La&&j.textShadow?(i=j.textShadow,j.textShadow=""):k&&k(P),b=f.getBBox?x({},f.getBBox()):{width:f.offsetWidth,height:f.offsetHeight},i?j.textShadow=i:k&&k("")}catch(m){}if(!b||b.width<0)b={width:0,height:0}}else b=this.htmlGetBBox();if(c.isSVG){a=b.width;d=b.height;if(ya&&
-g&&g.fontSize==="11px"&&d.toPrecision(3)==="16.9")b.height=d=14;if(e)b.width=O(d*aa(h))+O(a*X(h)),b.height=O(d*X(h))+O(a*aa(h))}c.cache[l]=b}return b},show:function(a){a&&this.element.namespaceURI===Ca?this.element.removeAttribute("visibility"):this.attr({visibility:a?"inherit":"visible"});return this},hide:function(){return this.attr({visibility:"hidden"})},fadeOut:function(a){var b=this;b.animate({opacity:0},{duration:a||150,complete:function(){b.attr({y:-9999})}})},add:function(a){var b=this.renderer,
-c=this.element,d;if(a)this.parentGroup=a;this.parentInverted=a&&a.inverted;this.textStr!==void 0&&b.buildText(this);this.added=!0;if(!a||a.handleZ||this.zIndex)d=this.zIndexSetter();d||(a?a.element:b.box).appendChild(c);if(this.onAdd)this.onAdd();return this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||{},c=a.shadows,d=a.renderer.isSVG&&b.nodeName==="SPAN"&&a.parentGroup,e,f;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=b.point=
-null;db(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(f=0;f]*>/g,"")))},textSetter:function(a){if(a!==this.textStr)delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this)},fillSetter:function(a,b,c){typeof a==="string"?c.setAttribute(b,a):a&&this.colorGradient(a,b,c)},zIndexSetter:function(a,b){var c=this.renderer,d=this.parentGroup,c=(d||c).element||c.box,e,f,g=this.element,h;e=this.added;var i;q(a)&&(g.setAttribute(b,a),a=+a,this[b]===a&&(e=!1),this[b]=a);if(e){if((a=this.zIndex)&&d)d.handleZ=!0;d=c.childNodes;for(i=0;i<
-d.length&&!h;i++)if(e=d[i],f=J(e,"zIndex"),e!==g&&(D(f)>a||!q(a)&&q(f)))c.insertBefore(g,e),h=!0;h||c.appendChild(g)}return h},_defaultSetter:function(a,b,c){c.setAttribute(b,a)}};Q.prototype.yGetter=Q.prototype.xGetter;Q.prototype.translateXSetter=Q.prototype.translateYSetter=Q.prototype.rotationSetter=Q.prototype.verticalAlignSetter=Q.prototype.scaleXSetter=Q.prototype.scaleYSetter=function(a,b){this[b]=a;this.doTransform=!0};Q.prototype["stroke-widthSetter"]=Q.prototype.strokeSetter=function(a,
-b,c){this[b]=a;if(this.stroke&&this["stroke-width"])this.strokeWidth=this["stroke-width"],Q.prototype.fillSetter.call(this,this.stroke,"stroke",c),c.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0;else if(b==="stroke-width"&&a===0&&this.hasStroke)c.removeAttribute("stroke"),this.hasStroke=!1};var ua=function(){this.init.apply(this,arguments)};ua.prototype={Element:Q,init:function(a,b,c,d,e){var f=location,g,d=this.createElement("svg").attr({version:"1.1"}).css(this.getStyle(d));
-g=d.element;a.appendChild(g);a.innerHTML.indexOf("xmlns")===-1&&J(g,"xmlns",Ca);this.isSVG=!0;this.box=g;this.boxWrapper=d;this.alignedObjects=[];this.url=(La||ib)&&B.getElementsByTagName("base").length?f.href.replace(/#.*?$/,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(B.createTextNode("Created with Highcharts 4.1.7"));this.defs=this.createElement("defs").add();this.forExport=e;this.gradients={};this.cache={};this.setSize(b,c,!1);var h;
-if(La&&a.getBoundingClientRect)this.subPixelFix=b=function(){L(a,{left:0,top:0});h=a.getBoundingClientRect();L(a,{left:ta(h.left)-h.left+"px",top:ta(h.top)-h.top+"px"})},b(),H(K,"resize",b)},getStyle:function(a){return this.style=x({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();Qa(this.gradients||
-{});this.gradients=null;if(a)this.defs=a.destroy();this.subPixelFix&&Z(K,"resize",this.subPixelFix);return this.alignedObjects=null},createElement:function(a){var b=new this.Element;b.init(this,a);return b},draw:function(){},buildText:function(a){for(var b=a.element,c=this,d=c.forExport,e=p(a.textStr,"").toString(),f=e.indexOf("<")!==-1,g=b.childNodes,h,i,j=J(b,"x"),k=a.styles,l=a.textWidth,m=k&&k.lineHeight,n=k&&k.textShadow,v=k&&k.textOverflow==="ellipsis",s=g.length,S=l&&!a.added&&this.box,N=function(a){return m?
-D(m):c.fontMetrics(/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:k&&k.fontSize||c.style.fontSize||12,a).h},t=function(a){return a.replace(/</g,"<").replace(/>/g,">")};s--;)b.removeChild(g[s]);!f&&!n&&!v&&e.indexOf(" ")===-1?b.appendChild(B.createTextNode(t(e))):(h=/<.*style="([^"]+)".*>/,i=/<.*href="(http[^"]+)".*>/,S&&S.appendChild(b),e=f?e.replace(/<(b|strong)>/g,'').replace(/<(i|em)>/g,'').replace(//g,
-"").split(//g):[e],e[e.length-1]===""&&e.pop(),o(e,function(e,f){var g,m=0,e=e.replace(//g,"|||");g=e.split("|||");o(g,function(e){if(e!==""||g.length===1){var n={},s=B.createElementNS(Ca,"tspan"),p;h.test(e)&&(p=e.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),J(s,"style",p));i.test(e)&&!d&&(J(s,"onclick",'location.href="'+e.match(i)[1]+'"'),L(s,{cursor:"pointer"}));e=t(e.replace(/<(.|\n)*?>/g,"")||" ");if(e!==" "){s.appendChild(B.createTextNode(e));
-if(m)n.dx=0;else if(f&&j!==null)n.x=j;J(s,n);b.appendChild(s);!m&&f&&(!ca&&d&&L(s,{display:"block"}),J(s,"dy",N(s)));if(l){for(var n=e.replace(/([^\^])-/g,"$1- ").split(" "),o=g.length>1||f||n.length>1&&k.whiteSpace!=="nowrap",S,w,q,u=[],y=N(s),r=1,x=a.rotation,z=e,C=z.length;(o||v)&&(n.length||u.length);)a.rotation=0,S=a.getBBox(!0),q=S.width,!ca&&c.forExport&&(q=c.measureSpanWidth(s.firstChild.data,a.styles)),S=q>l,w===void 0&&(w=S),v&&w?(C/=2,z===""||!S&&C<0.5?n=[]:(S&&(w=!0),z=e.substring(0,z.length+
-(S?-1:1)*ta(C)),n=[z+(l>3?"鈥�":"")],s.removeChild(s.firstChild))):!S||n.length===1?(n=u,u=[],n.length&&(r++,s=B.createElementNS(Ca,"tspan"),J(s,{dy:y,x:j}),p&&J(s,"style",p),b.appendChild(s)),q>l&&(l=q)):(s.removeChild(s.firstChild),u.unshift(n.pop())),n.length&&s.appendChild(B.createTextNode(n.join(" ").replace(/- /g,"-")));w&&a.attr("title",a.textStr);a.rotation=x}m++}}})}),S&&S.removeChild(b),n&&a.applyTextShadow&&a.applyTextShadow(n))},getContrast:function(a){a=oa(a).rgba;return a[0]+a[1]+a[2]>
-384?"#000000":"#FFFFFF"},button:function(a,b,c,d,e,f,g,h,i){var j=this.label(a,b,c,i,null,null,null,null,"button"),k=0,l,m,n,v,s,p,a={x1:0,y1:0,x2:0,y2:1},e=z({"stroke-width":1,stroke:"#CCCCCC",fill:{linearGradient:a,stops:[[0,"#FEFEFE"],[1,"#F6F6F6"]]},r:2,padding:5,style:{color:"black"}},e);n=e.style;delete e.style;f=z(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#FFF"],[1,"#ACF"]]}},f);v=f.style;delete f.style;g=z(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#9BD"],[1,"#CDF"]]}},g);
-s=g.style;delete g.style;h=z(e,{style:{color:"#CCC"}},h);p=h.style;delete h.style;H(j.element,ya?"mouseover":"mouseenter",function(){k!==3&&j.attr(f).css(v)});H(j.element,ya?"mouseout":"mouseleave",function(){k!==3&&(l=[e,f,g][k],m=[n,v,s][k],j.attr(l).css(m))});j.setState=function(a){(j.state=k=a)?a===2?j.attr(g).css(s):a===3&&j.attr(h).css(p):j.attr(e).css(n)};return j.on("click",function(){k!==3&&d.call(j)}).attr(e).css(x({cursor:"default"},n))},crispLine:function(a,b){a[1]===a[4]&&(a[1]=a[4]=
-r(a[1])-b%2/2);a[2]===a[5]&&(a[2]=a[5]=r(a[2])+b%2/2);return a},path:function(a){var b={fill:P};Ha(a)?b.d=a:da(a)&&x(b,a);return this.createElement("path").attr(b)},circle:function(a,b,c){a=da(a)?a:{x:a,y:b,r:c};b=this.createElement("circle");b.xSetter=function(a){this.element.setAttribute("cx",a)};b.ySetter=function(a){this.element.setAttribute("cy",a)};return b.attr(a)},arc:function(a,b,c,d,e,f){if(da(a))b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x;a=this.symbol("arc",a||0,b||0,c||0,c||0,{innerR:d||
-0,start:e||0,end:f||0});a.r=c;return a},rect:function(a,b,c,d,e,f){var e=da(a)?a.r:e,g=this.createElement("rect"),a=da(a)?a:a===y?{}:{x:a,y:b,width:u(c,0),height:u(d,0)};if(f!==y)a.strokeWidth=f,a=g.crisp(a);if(e)a.r=e;g.rSetter=function(a){J(this.element,{rx:a,ry:a})};return g.attr(a)},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[p(c,!0)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");
-return q(a)?b.attr({"class":"highcharts-"+a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:P};arguments.length>1&&x(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink","href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,b,c,d,e,f){var g,h=this.symbols[a],h=h&&h(r(b),r(c),d,e,f),i=/^url\((.*?)\)$/,j,k;if(h)g=this.path(h),x(g,{symbolName:a,x:b,y:c,width:d,height:e}),
-f&&x(g,f);else if(i.test(a))k=function(a,b){a.element&&(a.attr({width:b[0],height:b[1]}),a.alignByTranslate||a.translate(r((d-b[0])/2),r((e-b[1])/2)))},j=a.match(i)[1],a=Lb[j]||f&&f.width&&f.height&&[f.width,f.height],g=this.image(j).attr({x:b,y:c}),g.isImg=!0,a?k(g,a):(g.attr({width:0,height:0}),$("img",{onload:function(){k(g,Lb[j]=[this.width,this.height])},src:j}));return g},symbols:{circle:function(a,b,c,d){var e=0.166*c;return["M",a+c/2,b,"C",a+c+e,b,a+c+e,b+d,a+c/2,b+d,"C",a-e,b+d,a-e,b,a+c/
-2,b,"Z"]},square:function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d/2,a+c/2,b+d,a,b+d/2,"Z"]},arc:function(a,b,c,d,e){var f=e.start,c=e.r||c||d,g=e.end-0.001,d=e.innerR,h=e.open,i=X(f),j=aa(f),k=X(g),g=aa(g),e=e.end-fc&&e>b+g&&eb+g&&ed&&h>a+g&&ha+g&&hm&&/[ \-]/.test(b.textContent||b.innerText))L(b,{width:m+"px",display:"block",whiteSpace:j&&j.whiteSpace||"normal"}),i=m;this.getSpanCorrection(i,l,h,k,g)}L(b,{left:e+(this.xCorr||0)+"px",top:f+(this.yCorr||0)+"px"});if(ib)l=b.offsetHeight;this.cTT=n}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,c){var d={},e=ya?"-ms-transform":ib?"-webkit-transform":La?"MozTransform":Jb?"-o-transform":"";d[e]=d.transform="rotate("+a+"deg)";
-d[e+(La?"Origin":"-origin")]=d.transformOrigin=b*100+"% "+c+"px";L(this.element,d)},getSpanCorrection:function(a,b,c){this.xCorr=-a*c;this.yCorr=-b}});x(ua.prototype,{html:function(a,b,c){var d=this.createElement("span"),e=d.element,f=d.renderer;d.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;e.innerHTML=this.textStr=a};d.xSetter=d.ySetter=d.alignSetter=d.rotationSetter=function(a,b){b==="align"&&(b="textAlign");d[b]=a;d.htmlUpdateTransform()};d.attr({text:a,x:r(b),y:r(c)}).css({position:"absolute",
-fontFamily:this.style.fontFamily,fontSize:this.style.fontSize});e.style.whiteSpace="nowrap";d.css=d.htmlCss;if(f.isSVG)d.add=function(a){var b,c=f.box.parentNode,j=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)j.push(a),a=a.parentGroup;o(j.reverse(),function(a){var d,e=J(a.element,"class");e&&(e={className:e});b=a.div=a.div||$(Ka,e,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px"},b||c);d=b.style;x(a,{translateXSetter:function(b,c){d.left=b+"px";a[c]=b;a.doTransform=
-!0},translateYSetter:function(b,c){d.top=b+"px";a[c]=b;a.doTransform=!0},visibilitySetter:function(a,b){d[b]=a}})})}}else b=c;b.appendChild(e);d.added=!0;d.alignOnAdd&&d.htmlUpdateTransform();return d};return d}});if(!ca&&!fa){F={init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ","absolute",";"],e=b===Ka;(b==="shape"||e)&&d.push("left:0;top:0;width:1px;height:1px;");d.push("visibility: ",e?"hidden":"visible");c.push(' style="',d.join(""),'"/>');if(b)c=e||b==="span"||b==="img"?
-c.join(""):a.prepVML(c),this.element=$(c);this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();if(this.onAdd)this.onAdd();return this},updateTransform:Q.prototype.htmlUpdateTransform,setSpanRotation:function(){var a=this.rotation,b=X(a*ha),c=aa(a*ha);L(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11=",b,
-", M12=",-c,", M21=",c,", M22=",b,", sizingMethod='auto expand')"].join(""):P})},getSpanCorrection:function(a,b,c,d,e){var f=d?X(d*ha):1,g=d?aa(d*ha):0,h=p(this.elemHeight,this.element.offsetHeight),i;this.xCorr=f<0&&-a;this.yCorr=g<0&&-h;i=f*g<0;this.xCorr+=g*b*(i?1-c:c);this.yCorr-=f*b*(d?i?c:1-c:1);e&&e!=="left"&&(this.xCorr-=a*c*(f<0?-1:1),d&&(this.yCorr-=h*c*(g<0?-1:1)),L(this.element,{textAlign:e}))},pathToVML:function(a){for(var b=a.length,c=[];b--;)if(ra(a[b]))c[b]=r(a[b]*10)-5;else if(a[b]===
-"Z")c[b]="x";else if(c[b]=a[b],a.isArc&&(a[b]==="wa"||a[b]==="at"))c[b+5]===c[b+7]&&(c[b+7]+=a[b+7]>a[b+5]?1:-1),c[b+6]===c[b+8]&&(c[b+8]+=a[b+8]>a[b+6]?1:-1);return c.join(" ")||"x"},clip:function(a){var b=this,c;a?(c=a.members,ja(c,b),c.push(b),b.destroyClip=function(){ja(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:hb?"inherit":"rect(auto)"});return b.css(a)},css:Q.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&Ra(a)},destroy:function(){this.destroyClip&&this.destroyClip();
-return Q.prototype.destroy.apply(this)},on:function(a,b){this.element["on"+a]=function(){var a=K.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a,b){var c,a=a.split(/[ ,]/);c=a.length;if(c===9||c===11)a[c-4]=a[c-2]=D(a[c-2])-10*b;return a.join(" ")},shadow:function(a,b,c){var d=[],e,f=this.element,g=this.renderer,h,i=f.style,j,k=f.path,l,m,n,v;k&&typeof k.value!=="string"&&(k="x");m=k;if(a){n=p(a.width,3);v=(a.opacity||0.15)/n;for(e=1;e<=3;e++){l=n*2+1-2*e;c&&(m=this.cutOffPath(k.value,
-l+0.5));j=[' '];h=$(g.prepVML(j),null,{left:D(i.left)+p(a.offsetX,1),top:D(i.top)+p(a.offsetY,1)});if(c)h.cutOff=l+1;j=[' '];$(g.prepVML(j),null,null,h);b?b.element.appendChild(h):f.parentNode.insertBefore(h,f);d.push(h)}this.shadows=d}return this},updateShadows:na,setAttr:function(a,b){hb?this.element[a]=b:this.element.setAttribute(a,
-b)},classSetter:function(a){this.element.className=a},dashstyleSetter:function(a,b,c){(c.getElementsByTagName("stroke")[0]||$(this.renderer.prepVML([" "]),null,null,c))[b]=a||"solid";this[b]=a},dSetter:function(a,b,c){var d=this.shadows,a=a||[];this.d=a.join&&a.join(" ");c.path=a=this.pathToVML(a);if(d)for(c=d.length;c--;)d[c].path=d[c].cutOff?this.cutOffPath(a,d[c].cutOff):a;this.setAttr(b,a)},fillSetter:function(a,b,c){var d=c.nodeName;if(d==="SPAN")c.style.color=a;else if(d!=="IMG")c.filled=
-a!==P,this.setAttr("fillcolor",this.renderer.color(a,c,b,this))},opacitySetter:na,rotationSetter:function(a,b,c){c=c.style;this[b]=c[b]=a;c.left=-r(aa(a*ha)+1)+"px";c.top=r(X(a*ha))+"px"},strokeSetter:function(a,b,c){this.setAttr("strokecolor",this.renderer.color(a,c,b))},"stroke-widthSetter":function(a,b,c){c.stroked=!!a;this[b]=a;ra(a)&&(a+="px");this.setAttr("strokeweight",a)},titleSetter:function(a,b){this.setAttr(b,a)},visibilitySetter:function(a,b,c){a==="inherit"&&(a="visible");this.shadows&&
-o(this.shadows,function(c){c.style[b]=a});c.nodeName==="DIV"&&(a=a==="hidden"?"-999em":0,hb||(c.style[b]=a?"visible":"hidden"),b="top");c.style[b]=a},xSetter:function(a,b,c){this[b]=a;b==="x"?b="left":b==="y"&&(b="top");this.updateClipping?(this[b]=a,this.updateClipping()):c.style[b]=a},zIndexSetter:function(a,b,c){c.style[b]=a}};A.VMLElement=F=ka(Q,F);F.prototype.ySetter=F.prototype.widthSetter=F.prototype.heightSetter=F.prototype.xSetter;var Na={Element:F,isIE8:Ba.indexOf("MSIE 8.0")>-1,init:function(a,
-b,c,d){var e;this.alignedObjects=[];d=this.createElement(Ka).css(x(this.getStyle(d),{position:"relative"}));e=d.element;a.appendChild(d.element);this.isVML=!0;this.box=e;this.boxWrapper=d;this.cache={};this.setSize(b,c,!1);if(!B.namespaces.hcv){B.namespaces.add("hcv","urn:schemas-microsoft-com:vml");try{B.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}catch(f){B.styleSheets[0].cssText+="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}}},
-isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=da(a);return x(e,{members:[],count:0,left:(f?a.x:a)+1,top:(f?a.y:b)+1,width:(f?a.width:c)-1,height:(f?a.height:d)-1,getCSS:function(a){var b=a.element,c=b.nodeName,a=a.inverted,d=this.top-(c==="shape"?b.offsetTop:0),e=this.left,b=e+this.width,f=d+this.height,d={clip:"rect("+r(a?e:d)+"px,"+r(a?f:b)+"px,"+r(a?b:f)+"px,"+r(a?d:e)+"px)"};!a&&hb&&c==="DIV"&&x(d,{width:b+"px",height:f+"px"});return d},
-updateClipping:function(){o(e.members,function(a){a.element&&a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var e=this,f,g=/^rgba/,h,i,j=P;a&&a.linearGradient?i="gradient":a&&a.radialGradient&&(i="pattern");if(i){var k,l,m=a.linearGradient||a.radialGradient,n,v,s,p,N,t="",a=a.stops,w,ga=[],q=function(){h=[' '];$(e.prepVML(h),null,null,b)};n=a[0];w=a[a.length-1];n[0]>0&&a.unshift([0,n[1]]);
-w[0]<1&&a.push([1,w[1]]);o(a,function(a,b){g.test(a[1])?(f=oa(a[1]),k=f.get("rgb"),l=f.get("a")):(k=a[1],l=1);ga.push(a[0]*100+"% "+k);b?(s=l,p=k):(v=l,N=k)});if(c==="fill")if(i==="gradient")c=m.x1||m[0]||0,a=m.y1||m[1]||0,n=m.x2||m[2]||0,m=m.y2||m[3]||0,t='angle="'+(90-W.atan((m-a)/(n-c))*180/ma)+'"',q();else{var j=m.r,u=j*2,y=j*2,r=m.cx,x=m.cy,C=b.radialReference,z,j=function(){C&&(z=d.getBBox(),r+=(C[0]-z.x)/z.width-0.5,x+=(C[1]-z.y)/z.height-0.5,u*=C[2]/z.width,y*=C[2]/z.height);t='src="'+T.global.VMLRadialGradientURL+
-'" size="'+u+","+y+'" origin="0.5,0.5" position="'+r+","+x+'" color2="'+N+'" ';q()};d.added?j():d.onAdd=j;j=p}else j=k}else if(g.test(a)&&b.tagName!=="IMG")f=oa(a),h=["<",c,' opacity="',f.get("a"),'"/>'],$(this.prepVML(h),null,null,b),j=f.get("rgb");else{j=b.getElementsByTagName(c);if(j.length)j[0].opacity=1,j[0].type="solid";j=a}return j},prepVML:function(a){var b=this.isIE8,a=a.join("");b?(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=a.indexOf('style="')===-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):
-a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')):a=a.replace("<","1&&f.attr({x:b,y:c,width:d,height:e});return f},createElement:function(a){return a==="rect"?this.symbol(a):ua.prototype.createElement.call(this,a)},invertChild:function(a,b){var c=this,d=b.style,e=a.tagName==="IMG"&&a.style;L(a,{flip:"x",left:D(d.width)-(e?D(e.top):1),top:D(d.height)-(e?D(e.left):1),rotation:-90});o(a.childNodes,function(b){c.invertChild(b,a)})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c||
-d,c=e.innerR,d=X(f),i=aa(f),j=X(g),k=aa(g);if(g-f===0)return["x"];f=["wa",a-h,b-h,a+h,b+h,a+h*d,b+h*i,a+h*j,b+h*k];e.open&&!c&&f.push("e","M",a,b);f.push("at",a-c,b-c,a+c,b+c,a+c*j,b+c*k,a+c*d,b+c*i,"x","e");f.isArc=!0;return f},circle:function(a,b,c,d,e){e&&(c=d=2*e.r);e&&e.isCircle&&(a-=c/2,b-=d/2);return["wa",a,b,a+c,b+d,a+c,b+d/2,a+c,b+d/2,"e"]},rect:function(a,b,c,d,e){return ua.prototype.symbols[!q(e)||!e.r?"square":"callout"].call(0,a,b,c,d,e)}}};A.VMLRenderer=F=function(){this.init.apply(this,
-arguments)};F.prototype=z(ua.prototype,Na);$a=F}ua.prototype.measureSpanWidth=function(a,b){var c=B.createElement("span"),d;d=B.createTextNode(a);c.appendChild(d);L(c,b);this.box.appendChild(c);d=c.offsetWidth;Ra(c);return d};var Mb;if(fa)A.CanVGRenderer=F=function(){Ca="http://www.w3.org/1999/xhtml"},F.prototype.symbols={},Mb=function(){function a(){var a=b.length,d;for(d=0;d0&&c+i*j>e&&(m=r((d-c)/X(h*ha)));else if(d=c+
-(1-i)*j,c-i*je&&(k=e-a.x+k*i,l=-1),k=C(b.slotWidth,k),kk||b.autoRotation&&g.styles.width)m=k;if(m){n.width=m;if(!b.options.labels.style.textOverflow)n.textOverflow="ellipsis";g.css(n)}},getPosition:function(a,b,c,d){var e=this.axis,f=e.chart,g=d&&f.oldChartHeight||f.chartHeight;return{x:a?e.translate(b+c,null,null,d)+e.transB:e.left+e.offset+(e.opposite?(d&&f.oldChartWidth||f.chartWidth)-
-e.right-e.left:0),y:a?g-e.bottom+e.offset-(e.opposite?e.height:0):g-e.translate(b+c,null,null,d)-e.transB}},getLabelPosition:function(a,b,c,d,e,f,g,h){var i=this.axis,j=i.transA,k=i.reversed,l=i.staggerLines,m=i.tickRotCorr||{x:0,y:0},c=p(e.y,m.y+(i.side===2?8:-(c.getBBox().height/2))),a=a+e.x+m.x-(f&&d?f*j*(k?-1:1):0),b=b+c-(f&&!d?f*j*(k?1:-1):0);l&&(b+=g/(h||1)%l*(i.labelOffset/l));return{x:a,y:r(b)}},getMarkPath:function(a,b,c,d,e,f){return f.crispLine(["M",a,b,"L",a+(e?0:-c),b+(e?c:0)],d)},render:function(a,
-b,c){var d=this.axis,e=d.options,f=d.chart.renderer,g=d.horiz,h=this.type,i=this.label,j=this.pos,k=e.labels,l=this.gridLine,m=h?h+"Grid":"grid",n=h?h+"Tick":"tick",v=e[m+"LineWidth"],s=e[m+"LineColor"],o=e[m+"LineDashStyle"],N=e[n+"Length"],m=e[n+"Width"]||0,t=e[n+"Color"],w=e[n+"Position"],n=this.mark,ga=k.step,q=!0,u=d.tickmarkOffset,r=this.getPosition(g,j,u,b),x=r.x,r=r.y,z=g&&x===d.pos+d.len||!g&&r===d.pos?-1:1,c=p(c,1);this.isActive=!0;if(v){j=d.getPlotLinePath(j+u,v*z,b,!0);if(l===y){l={stroke:s,
-"stroke-width":v};if(o)l.dashstyle=o;if(!h)l.zIndex=1;if(b)l.opacity=0;this.gridLine=l=v?f.path(j).attr(l).add(d.gridGroup):null}if(!b&&l&&j)l[this.isNew?"attr":"animate"]({d:j,opacity:c})}if(m&&N)w==="inside"&&(N=-N),d.opposite&&(N=-N),h=this.getMarkPath(x,r,N,m*z,g,f),n?n.animate({d:h,opacity:c}):this.mark=f.path(h).attr({stroke:t,"stroke-width":m,opacity:c}).add(d.axisGroup);if(i&&!isNaN(x))i.xy=r=this.getLabelPosition(x,r,i,g,k,u,a,ga),this.isFirst&&!this.isLast&&!p(e.showFirstLabel,1)||this.isLast&&
-!this.isFirst&&!p(e.showLastLabel,1)?q=!1:g&&!d.isRadial&&!k.step&&!k.rotation&&!b&&c!==0&&this.handleOverflow(r),ga&&a%ga&&(q=!1),q&&!isNaN(r.y)?(r.opacity=c,i[this.isNew?"attr":"animate"](r),this.isNew=!1):i.attr("y",-9999)},destroy:function(){Qa(this,this.axis)}};A.PlotLineOrBand=function(a,b){this.axis=a;if(b)this.options=b,this.id=b.id};A.PlotLineOrBand.prototype={render:function(){var a=this,b=a.axis,c=b.horiz,d=a.options,e=d.label,f=a.label,g=d.width,h=d.to,i=d.from,j=q(i)&&q(h),k=d.value,
-l=d.dashStyle,m=a.svgElem,n=[],v,s=d.color,p=d.zIndex,o=d.events,t={},w=b.chart.renderer;b.isLog&&(i=Ea(i),h=Ea(h),k=Ea(k));if(g){if(n=b.getPlotLinePath(k,g),t={stroke:s,"stroke-width":g},l)t.dashstyle=l}else if(j){n=b.getPlotBandPath(i,h,d);if(s)t.fill=s;if(d.borderWidth)t.stroke=d.borderColor,t["stroke-width"]=d.borderWidth}else return;if(q(p))t.zIndex=p;if(m)if(n)m.animate({d:n},null,m.onGetPath);else{if(m.hide(),m.onGetPath=function(){m.show()},f)a.label=f=f.destroy()}else if(n&&n.length&&(a.svgElem=
-m=w.path(n).attr(t).add(),o))for(v in d=function(b){m.on(b,function(c){o[b].apply(a,[c])})},o)d(v);if(e&&q(e.text)&&n&&n.length&&b.width>0&&b.height>0){e=z({align:c&&j&&"center",x:c?!j&&4:10,verticalAlign:!c&&j&&"middle",y:c?j?16:10:j?6:-4,rotation:c&&!j&&90},e);if(!f){t={align:e.textAlign||e.align,rotation:e.rotation};if(q(p))t.zIndex=p;a.label=f=w.text(e.text,0,0,e.useHTML).attr(t).css(e.style).add()}b=[n[1],n[4],j?n[6]:n[1]];j=[n[2],n[5],j?n[7]:n[2]];n=Pa(b);c=Pa(j);f.align(e,!1,{x:n,y:c,width:Fa(b)-
-n,height:Fa(j)-c});f.show()}else f&&f.hide();return a},destroy:function(){ja(this.axis.plotLinesAndBands,this);delete this.axis;Qa(this)}};var va=A.Axis=function(){this.init.apply(this,arguments)};va.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,gridLineColor:"#D8D8D8",labels:{enabled:!0,style:{color:"#606060",cursor:"default",fontSize:"11px"},x:0,y:15},lineColor:"#C0D0E0",
-lineWidth:1,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickColor:"#C0D0E0",tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#707070"}},type:"linear"},defaultYAxisOptions:{endOnTick:!0,gridLineWidth:1,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8,y:3},lineWidth:0,maxPadding:0.05,
-minPadding:0.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return A.numberFormat(this.total,-1)},style:z(ba.line.dataLabels.style,{color:"#000000"})}},defaultLeftAxisOptions:{labels:{x:-15,y:null},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15,y:null},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0,y:null},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45],x:0,y:-15},title:{rotation:0}},
-init:function(a,b){var c=b.isX;this.horiz=a.inverted?!c:c;this.coll=(this.isXAxis=c)?"xAxis":"yAxis";this.opposite=b.opposite;this.side=b.side||(this.horiz?this.opposite?0:2:this.opposite?1:3);this.setOptions(b);var d=this.options,e=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.userOptions=b;this.minPixelPadding=0;this.chart=a;this.reversed=d.reversed;this.zoomEnabled=d.zoomEnabled!==!1;this.categories=d.categories||e==="category";this.names=this.names||[];this.isLog=
-e==="logarithmic";this.isDatetimeAxis=e==="datetime";this.isLinked=q(d.linkedTo);this.ticks={};this.labelEdge=[];this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len=0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range;this.offset=d.offset||0;this.stacks={};this.oldStacks={};this.min=this.max=null;this.crosshair=p(d.crosshair,sa(a.options.tooltip.crosshairs)[c?0:1],!1);var f,d=this.options.events;Ma(this,a.axes)===-1&&(c&&!this.isColorAxis?a.axes.splice(a.xAxis.length,
-0,this):a.axes.push(this),a[this.coll].push(this));this.series=this.series||[];if(a.inverted&&c&&this.reversed===y)this.reversed=!0;this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in d)H(this,f,d[f]);if(this.isLog)this.val2lin=Ea,this.lin2val=ia},setOptions:function(a){this.options=z(this.defaultOptions,this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],z(T[this.coll],
-a))},defaultLabelFormatter:function(){var a=this.axis,b=this.value,c=a.categories,d=this.dateTimeLabelFormat,e=T.lang.numericSymbols,f=e&&e.length,g,h=a.options.labels.format,a=a.isLog?b:a.tickInterval;if(h)g=Ja(h,this);else if(c)g=b;else if(d)g=Oa(d,b);else if(f&&a>=1E3)for(;f--&&g===y;)c=Math.pow(1E3,f+1),a>=c&&b*10%c===0&&e[f]!==null&&(g=A.numberFormat(b/c,-1)+e[f]);g===y&&(g=O(b)>=1E4?A.numberFormat(b,-1):A.numberFormat(b,-1,y,""));return g},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=
-!1;a.dataMin=a.dataMax=a.ignoreMinPadding=a.ignoreMaxPadding=null;a.buildStacks&&a.buildStacks();o(a.series,function(c){if(c.visible||!b.options.chart.ignoreHiddenSeries){var d;d=c.options.threshold;var e;a.hasVisibleSeries=!0;a.isLog&&d<=0&&(d=null);if(a.isXAxis){if(d=c.xData,d.length)a.dataMin=C(p(a.dataMin,d[0]),Pa(d)),a.dataMax=u(p(a.dataMax,d[0]),Fa(d))}else{c.getExtremes();e=c.dataMax;c=c.dataMin;if(q(c)&&q(e))a.dataMin=C(p(a.dataMin,c),c),a.dataMax=u(p(a.dataMax,e),e);if(q(d))if(a.dataMin>=
-d)a.dataMin=d,a.ignoreMinPadding=!0;else if(a.dataMaxc)d?a=C(u(b,a),c):m=!0;return a},e=p(e,this.translate(a,null,null,c)),a=c=r(e+i);i=j=r(k-e-i);isNaN(e)?m=!0:this.horiz?(i=h,j=k-this.bottom,a=c=n(a,
-g,g+this.width)):(a=g,c=l-this.right,i=j=n(i,h,h+this.height));return m&&!d?null:f.renderer.crispLine(["M",a,i,"L",c,j],b||1)},getLinearTickPositions:function(a,b,c){var d,e=ea(V(b/a)*a),f=ea(ta(c/a)*a),g=[];if(b===c&&ra(b))return[b];for(b=e;b<=f;){g.push(b);b=ea(b+a);if(b===d)break;d=b}return g},getMinorTickPositions:function(){var a=this.options,b=this.tickPositions,c=this.minorTickInterval,d=[],e,f=this.min;e=this.max;var g=e-f;if(g&&g/c=this.minRange,f,g,h,i,j;if(this.isXAxis&&this.minRange===y&&!this.isLog)q(a.min)||q(a.max)?this.minRange=null:(o(this.series,function(a){i=a.xData;for(g=j=a.xIncrement?1:
-i.length-1;g>0;g--)if(h=i[g]-i[g-1],f===y||hc&&(h=0);d=u(d,h);b.single||(f=u(f,Da(j)?0:h/2),g=u(g,j==="on"?0:h));!a.noSharedTooltip&&q(v)&&(e=q(e)?C(e,v):v)}),h=b.ordinalSlope&&e?b.ordinalSlope/e:1,b.minPointOffset=f*=h,b.pointRangePadding=g*=h,b.pointRange=C(d,c),k)b.closestPointRange=e;if(a)b.oldTransA=j;b.translationSlope=b.transA=j=b.len/(c+g||1);b.transB=b.horiz?b.left:b.bottom;b.minPixelPadding=
-j*f},setTickInterval:function(a){var b=this,c=b.chart,d=b.options,e=b.isLog,f=b.isDatetimeAxis,g=b.isXAxis,h=b.isLinked,i=d.maxPadding,j=d.minPadding,k=d.tickInterval,l=d.tickPixelInterval,m=b.categories;!f&&!m&&!h&&this.getTickAmount();h?(b.linkedParent=c[b.coll][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=p(c.min,c.dataMin),b.max=p(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&la(11,1)):(b.min=p(b.userMin,d.min,b.dataMin),b.max=p(b.userMax,d.max,b.dataMax));if(e)!a&&C(b.min,p(b.dataMin,
-b.min))<=0&&la(10,1),b.min=ea(Ea(b.min)),b.max=ea(Ea(b.max));if(b.range&&q(b.max))b.userMin=b.min=u(b.min,b.max-b.range),b.userMax=b.max,b.range=null;b.beforePadding&&b.beforePadding();b.adjustForMinRange();if(!m&&!b.axisPointRange&&!b.usePercentage&&!h&&q(b.min)&&q(b.max)&&(c=b.max-b.min)){if(!q(d.min)&&!q(b.userMin)&&j&&(b.dataMin<0||!b.ignoreMinPadding))b.min-=c*j;if(!q(d.max)&&!q(b.userMax)&&i&&(b.dataMax>0||!b.ignoreMaxPadding))b.max+=c*i}if(ra(d.floor))b.min=u(b.min,d.floor);if(ra(d.ceiling))b.max=
-C(b.max,d.ceiling);b.tickInterval=b.min===b.max||b.min===void 0||b.max===void 0?1:h&&!k&&l===b.linkedParent.options.tickPixelInterval?k=b.linkedParent.tickInterval:p(k,this.tickAmount?(b.max-b.min)/u(this.tickAmount-1,1):void 0,m?1:(b.max-b.min)*l/u(b.len,l));g&&!a&&o(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();if(b.postProcessTickInterval)b.tickInterval=b.postProcessTickInterval(b.tickInterval);
-if(b.pointRange)b.tickInterval=u(b.pointRange,b.tickInterval);a=p(d.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);if(!k&&b.tickInterval0.5&&b.tickInterval<5&&b.max>1E3&&b.max<9999)),!!this.tickAmount);if(!this.tickAmount&&this.len)b.tickInterval=b.unsquish();this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions,d=a.tickPositioner,
-e=a.startOnTick,f=a.endOnTick,g;this.tickmarkOffset=this.categories&&a.tickmarkPlacement==="between"&&this.tickInterval===1?0.5:0;this.minorTickInterval=a.minorTickInterval==="auto"&&this.tickInterval?this.tickInterval/5:a.minorTickInterval;this.tickPositions=b=c&&c.slice();if(!b&&(this.tickPositions=b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,
-this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),d&&(d=d.apply(this,[this.min,this.max]))))this.tickPositions=b=d;if(!this.isLinked)this.trimTicks(b,e,f),this.min===this.max&&q(this.min)&&!this.tickAmount&&(g=!0,this.min-=0.5,this.max+=0.5),this.single=g,!c&&!d&&this.adjustTickAmount()},trimTicks:function(a,b,c){var d=a[0],e=a[a.length-1],f=this.minPointOffset||0;b?this.min=d:this.min-f>d&&a.shift();c?this.max=e:this.max+fc&&(this.tickInterval*=2,this.setTickPositions());if(q(d)){for(a=c=b.length;a--;)(d===3&&a%2===1||d<=2&&a>0&&a=u(d,p(e.max,d))&&(b=y));this.displayBtn=a!==y||b!==y;this.setExtremes(a,
-b,!1,y,{trigger:"zoom"});return!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft||0,d=this.horiz,e=p(b.width,a.plotWidth-c+(b.offsetRight||0)),f=p(b.height,a.plotHeight),g=p(b.top,a.plotTop),b=p(b.left,a.plotLeft+c),c=/%$/;c.test(f)&&(f=parseFloat(f)/100*a.plotHeight);c.test(g)&&(g=parseFloat(g)/100*a.plotHeight+a.plotTop);this.left=b;this.top=g;this.width=e;this.height=f;this.bottom=a.chartHeight-f-g;this.right=a.chartWidth-e-b;this.len=u(d?e:f,0);this.pos=d?b:g},getExtremes:function(){var a=
-this.isLog;return{min:a?ea(ia(this.min)):this.min,max:a?ea(ia(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=b?ia(this.min):this.min,b=b?ia(this.max):this.max;a===null?a=b<0?b:c:c>a?a=c:b15&&a<165?"right":a>195&&a<345?"left":"center"},unsquish:function(){var a=this.ticks,b=this.options.labels,
-c=this.horiz,d=this.tickInterval,e=d,f=this.len/(((this.categories?1:0)+this.max-this.min)/d),g,h=b.rotation,i=this.chart.renderer.fontMetrics(b.style.fontSize,a[0]&&a[0].label),j,k=Number.MAX_VALUE,l,m=function(a){a/=f||1;a=a>1?ta(a):1;return a*d};c?(l=q(h)?[h]:f=-90&&a<=90)j=m(O(i.h/aa(ha*a))),b=j+O(a/360),bm)m=a.labelLength}),
-m>j&&m>g.h?k.rotation=this.labelRotation:this.labelRotation=0;else if(i&&(l={width:j+"px"},!h)){l.textOverflow="clip";for(i=c.length;!f&&i--;)if(j=c[i],j=d[j].label)if(j.styles.textOverflow==="ellipsis"&&j.css({textOverflow:"clip"}),j.getBBox().height>this.len/c.length-(g.h-g.f))j.specCss={textOverflow:"ellipsis"}}if(k.rotation&&(l={width:(m>a.chartHeight*0.5?a.chartHeight*0.33:a.chartHeight)+"px"},!h))l.textOverflow="ellipsis";this.labelAlign=k.align=e.align||this.autoLabelAlign(this.labelRotation);
-o(c,function(a){var b=(a=d[a])&&a.label;if(b)l&&b.css(z(l,b.specCss)),delete b.specCss,b.attr(k),a.rotation=k.rotation});this.tickRotCorr=b.rotCorr(g.b,this.labelRotation||0,this.side===2)},hasData:function(){return this.hasVisibleSeries||q(this.min)&&q(this.max)&&!!this.tickPositions},getOffset:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.tickPositions,f=a.ticks,g=a.horiz,h=a.side,i=b.inverted?[1,0,3,2][h]:h,j,k,l=0,m,n=0,v=d.title,s=d.labels,S=0,N=b.axisOffset,b=b.clipOffset,t=[-1,
-1,1,-1][h],w;j=a.hasData();a.showAxis=k=j||p(d.showEmpty,!0);a.staggerLines=a.horiz&&s.staggerLines;if(!a.axisGroup)a.gridGroup=c.g("grid").attr({zIndex:d.gridZIndex||1}).add(),a.axisGroup=c.g("axis").attr({zIndex:d.zIndex||2}).add(),a.labelGroup=c.g("axis-labels").attr({zIndex:s.zIndex||7}).addClass("highcharts-"+a.coll.toLowerCase()+"-labels").add();if(j||a.isLinked){if(o(e,function(b){f[b]?f[b].addLabel():f[b]=new Ta(a,b)}),a.renderUnsquish(),o(e,function(b){if(h===0||h===2||{1:"left",3:"right"}[h]===
-a.labelAlign)S=u(f[b].getLabelSize(),S)}),a.staggerLines)S*=a.staggerLines,a.labelOffset=S}else for(w in f)f[w].destroy(),delete f[w];if(v&&v.text&&v.enabled!==!1){if(!a.axisTitle)a.axisTitle=c.text(v.text,0,0,v.useHTML).attr({zIndex:7,rotation:v.rotation||0,align:v.textAlign||{low:"left",middle:"center",high:"right"}[v.align]}).addClass("highcharts-"+this.coll.toLowerCase()+"-title").css(v.style).add(a.axisGroup),a.axisTitle.isNew=!0;if(k)l=a.axisTitle.getBBox()[g?"height":"width"],m=v.offset,n=
-q(m)?0:p(v.margin,g?5:10);a.axisTitle[k?"show":"hide"]()}a.offset=t*p(d.offset,N[h]);a.tickRotCorr=a.tickRotCorr||{x:0,y:0};c=h===2?a.tickRotCorr.y:0;g=S+n+(S&&t*(g?p(s.y,a.tickRotCorr.y+8):s.x)-c);a.axisTitleMargin=p(m,g);N[h]=u(N[h],a.axisTitleMargin+l+t*a.offset,g);l=V(d.lineWidth/2)*2;d.offset&&(l=u(0,l-d.offset));b[i]=u(b[i],l)},getLinePath:function(a){var b=this.chart,c=this.opposite,d=this.offset,e=this.horiz,f=this.left+(c?this.width:0)+d,d=b.chartHeight-this.bottom-(c?this.height:0)+d;c&&
-(a*=-1);return b.renderer.crispLine(["M",e?this.left:f,e?d:this.top,"L",e?b.chartWidth-this.right:f,e?d:b.chartHeight-this.bottom],a)},getTitlePosition:function(){var a=this.horiz,b=this.left,c=this.top,d=this.len,e=this.options.title,f=a?b:c,g=this.opposite,h=this.offset,i=e.x||0,j=e.y||0,k=D(e.style.fontSize||12),d={low:f+(a?0:d),middle:f+d/2,high:f+(a?d:0)}[e.align],b=(a?c+this.height:b)+(a?1:-1)*(g?-1:1)*this.axisTitleMargin+(this.side===2?k:0);return{x:a?d+i:b+(g?this.width:0)+h+i,y:a?b+j-(g?
-this.height:0)+h:d+j}},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.isLog,f=a.isLinked,g=a.tickPositions,h=a.axisTitle,i=a.ticks,j=a.minorTicks,k=a.alternateBands,l=d.stackLabels,m=d.alternateGridColor,n=a.tickmarkOffset,v=d.lineWidth,s,p=b.hasRendered&&q(a.oldMin)&&!isNaN(a.oldMin),N=a.showAxis,t,w;a.labelEdge.length=0;a.overlap=!1;o([i,j,k],function(a){for(var b in a)a[b].isActive=!1});if(a.hasData()||f){a.minorTickInterval&&!a.categories&&o(a.getMinorTickPositions(),function(b){j[b]||
-(j[b]=new Ta(a,b,"minor"));p&&j[b].isNew&&j[b].render(null,!0);j[b].render(null,!1,1)});if(g.length&&(o(g,function(b,c){if(!f||b>=a.min&&b<=a.max)i[b]||(i[b]=new Ta(a,b)),p&&i[b].isNew&&i[b].render(c,!0,0.1),i[b].render(c)}),n&&(a.min===0||a.single)))i[-1]||(i[-1]=new Ta(a,-1,null,!0)),i[-1].render(-1);m&&o(g,function(b,c){if(c%2===0&&b=E.second?0:k*V(i.getMilliseconds()/k));if(j>=E.second)i[Fb](j>=E.minute?0:k*V(i.getSeconds()/k));if(j>=E.minute)i[Gb](j>=E.hour?0:k*V(i[sb]()/k));if(j>=E.hour)i[Hb](j>=
-E.day?0:k*V(i[tb]()/k));if(j>=E.day)i[vb](j>=E.month?1:k*V(i[Xa]()/k));j>=E.month&&(i[wb](j>=E.year?0:k*V(i[Ya]()/k)),h=i[Za]());j>=E.year&&(h-=h%k,i[xb](h));if(j===E.week)i[vb](i[Xa]()-i[ub]()+p(d,1));b=1;if(ob||eb)i=i.getTime(),i=new Aa(i+Wa(i));h=i[Za]();for(var d=i.getTime(),l=i[Ya](),m=i[Xa](),n=(E.day+(g?Wa(i):i.getTimezoneOffset()*6E4))%E.day;d=0.5)a=r(a),g=this.getLinearTickPositions(a,b,c);else if(a>=0.08)for(var f=V(b),h,i,j,k,l,e=a>0.3?[1,2,4]:a>0.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];fb&&(!d||k<=c)&&k!==y&&g.push(k),k>c&&(l=!0),
-k=j}else if(b=ia(b),c=ia(c),a=e[d?"minorTickInterval":"tickInterval"],a=p(a==="auto"?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=qb(a,null,pb(a)),g=Ua(this.getLinearTickPositions(a,b,c),Ea),!d)this._minorAutoInterval=a/5;if(!d)this.tickInterval=a;return g};var Nb=A.Tooltip=function(){this.init.apply(this,arguments)};Nb.prototype={init:function(a,b){var c=b.borderWidth,d=b.style,e=D(d.padding);this.chart=a;this.options=b;this.crosshairs=
-[];this.now={x:0,y:0};this.isHidden=!0;this.label=a.renderer.label("",0,0,b.shape||"callout",null,null,b.useHTML,null,"tooltip").attr({padding:e,fill:b.backgroundColor,"stroke-width":c,r:b.borderRadius,zIndex:8}).css(d).css({padding:0}).add().attr({y:-9999});fa||this.label.shadow(b.shadow);this.shared=b.shared},destroy:function(){if(this.label)this.label=this.label.destroy();clearTimeout(this.hideTimer);clearTimeout(this.tooltipTimeout)},move:function(a,b,c,d){var e=this,f=e.now,g=e.options.animation!==
-!1&&!e.isHidden&&(O(a-f.x)>1||O(b-f.y)>1),h=e.followPointer||e.len>1;x(f,{x:g?(2*f.x+a)/3:a,y:g?(f.y+b)/2:b,anchorX:h?y:g?(2*f.anchorX+c)/3:c,anchorY:h?y:g?(f.anchorY+d)/2:d});e.label.attr(f);if(g)clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32)},hide:function(a){var b=this;clearTimeout(this.hideTimer);if(!this.isHidden)this.hideTimer=setTimeout(function(){b.label.fadeOut();b.isHidden=!0},p(a,this.options.hideDelay,500))},getAnchor:function(a,b){var c,
-d=this.chart,e=d.inverted,f=d.plotTop,g=d.plotLeft,h=0,i=0,j,k,a=sa(a);c=a[0].tooltipPos;this.followPointer&&b&&(b.chartX===y&&(b=d.pointer.normalize(b)),c=[b.chartX-d.plotLeft,b.chartY-f]);c||(o(a,function(a){j=a.series.yAxis;k=a.series.xAxis;h+=a.plotX+(!e&&k?k.left-g:0);i+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&j?j.top-f:0)}),h/=a.length,i/=a.length,c=[e?d.plotWidth-i:h,this.shared&&!e&&a.length>1&&b?b.chartY-f:e?d.plotHeight-h:i]);return Ua(c,r)},getPosition:function(a,b,c){var d=this.chart,
-e=this.distance,f={},g=c.h||0,h,i=["y",d.chartHeight,b,c.plotY+d.plotTop],j=["x",d.chartWidth,a,c.plotX+d.plotLeft],k=p(c.ttBelow,d.inverted&&!c.negative||!d.inverted&&c.negative),l=function(a,b,c,d){var h=cb?d:d+g;else return!1},m=function(a,b,c,d){if(db-e)return!1;else f[a]=db-c/2?b-c-2:d-c/2},n=function(a){var b=i;i=j;j=b;h=a},v=function(){l.apply(0,i)!==!1?m.apply(0,j)===
-!1&&!h&&(n(!0),v()):h?f.x=f.y=0:(n(!0),v())};(d.inverted||this.len>1)&&n();v();return f},defaultFormatter:function(a){var b=this.points||sa(this),c;c=[a.tooltipFooterHeaderFormatter(b[0])];c=c.concat(a.bodyFormatter(b));c.push(a.tooltipFooterHeaderFormatter(b[0],!0));return c.join("")},refresh:function(a,b){var c=this.chart,d=this.label,e=this.options,f,g,h,i={},j,k=[];j=e.formatter||this.defaultFormatter;var i=c.hoverPoints,l,m=this.shared;clearTimeout(this.hideTimer);this.followPointer=sa(a)[0].series.tooltipOptions.followPointer;
-h=this.getAnchor(a,b);f=h[0];g=h[1];m&&(!a.series||!a.series.noSharedTooltip)?(c.hoverPoints=a,i&&o(i,function(a){a.setState()}),o(a,function(a){a.setState("hover");k.push(a.getLabelConfig())}),i={x:a[0].category,y:a[0].y},i.points=k,this.len=k.length,a=a[0]):i=a.getLabelConfig();j=j.call(i,this);i=a.series;this.distance=p(i.tooltipOptions.distance,16);j===!1?this.hide():(this.isHidden&&(db(d),d.attr("opacity",1).show()),d.attr({text:j}),l=e.borderColor||a.color||i.color||"#606060",d.attr({stroke:l}),
-this.updatePosition({plotX:f,plotY:g,negative:a.negative,ttBelow:a.ttBelow,h:h[2]||0}),this.isHidden=!1);I(c,"tooltipRefresh",{text:j,x:f+c.plotLeft,y:g+c.plotTop,borderColor:l})},updatePosition:function(a){var b=this.chart,c=this.label,c=(this.options.positioner||this.getPosition).call(this,c.width,c.height,a);this.move(r(c.x),r(c.y||0),a.plotX+b.plotLeft,a.plotY+b.plotTop)},getXDateFormat:function(a,b,c){var d,b=b.dateTimeLabelFormats,e=c&&c.closestPointRange,f,g={millisecond:15,second:12,minute:9,
-hour:6,day:3},h,i="millisecond";if(e){h=Oa("%m-%d %H:%M:%S.%L",a.x);for(f in E){if(e===E.week&&+Oa("%w",a.x)===c.options.startOfWeek&&h.substr(6)==="00:00:00.000"){f="week";break}else if(E[f]>e){f=i;break}else if(g[f]&&h.substr(g[f])!=="01-01 00:00:00.000".substr(g[f]))break;f!=="week"&&(i=f)}f&&(d=b[f])}else d=b.day;return d||b.year},tooltipFooterHeaderFormatter:function(a,b){var c=b?"footer":"header",d=a.series,e=d.tooltipOptions,f=e.xDateFormat,g=d.xAxis,h=g&&g.options.type==="datetime"&&ra(a.key),
-c=e[c+"Format"];h&&!f&&(f=this.getXDateFormat(a,e,g));h&&f&&(c=c.replace("{point.key}","{point.key:"+f+"}"));return Ja(c,{point:a,series:d})},bodyFormatter:function(a){return Ua(a,function(a){var c=a.series.tooltipOptions;return(c.pointFormatter||a.point.tooltipFormatter).call(a.point,c.pointFormat)})}};var pa;ab=B.documentElement.ontouchstart!==y;var Va=A.Pointer=function(a,b){this.init(a,b)};Va.prototype={init:function(a,b){var c=b.chart,d=c.events,e=fa?"":c.zoomType,c=a.inverted,f;this.options=
-b;this.chart=a;this.zoomX=f=/x/.test(e);this.zoomY=e=/y/.test(e);this.zoomHor=f&&!c||e&&c;this.zoomVert=e&&!c||f&&c;this.hasZoom=f||e;this.runChartClick=d&&!!d.click;this.pinchDown=[];this.lastValidTouch={};if(A.Tooltip&&b.tooltip.enabled)a.tooltip=new Nb(a,b.tooltip),this.followTouchMove=p(b.tooltip.followTouchMove,!0);this.setDOMEvents()},normalize:function(a,b){var c,d,a=a||window.event,a=Tb(a);if(!a.target)a.target=a.srcElement;d=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:
-a;if(!b)this.chartPosition=b=Sb(this.chart.container);d.pageX===y?(c=u(a.x,a.clientX-b.left),d=a.y):(c=d.pageX-b.left,d=d.pageY-b.top);return x(a,{chartX:r(c),chartY:r(d)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};o(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},runPointActions:function(a){var b=this.chart,c=b.series,d=b.tooltip,e=d?d.shared:!1,f=b.hoverPoint,g=b.hoverSeries,h,i=b.chartWidth,j,k,l=[],m,
-n;if(!e&&!g)for(h=0;hh+j&&(d=h+j);ei+k&&(e=i+k);this.hasDragged=Math.sqrt(Math.pow(m-d,2)+Math.pow(n-e,2));if(this.hasDragged>10){l=b.isInsidePlot(m-h,n-i);if(b.hasCartesianSeries&&(this.zoomX||this.zoomY)&&l&&!v&&!this.selectionMarker)this.selectionMarker=
-b.renderer.rect(h,i,f?1:j,g?1:k,0).attr({fill:c.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add();this.selectionMarker&&f&&(d-=m,this.selectionMarker.attr({width:O(d),x:(d>0?0:d)+m}));this.selectionMarker&&g&&(d=e-n,this.selectionMarker.attr({height:O(d),y:(d>0?0:d)+n}));l&&!this.selectionMarker&&c.panning&&b.pan(a,c.panning)}},drop:function(a){var b=this,c=this.chart,d=this.hasPinched;if(this.selectionMarker){var e={xAxis:[],yAxis:[],originalEvent:a.originalEvent||a},f=this.selectionMarker,
-g=f.attr?f.attr("x"):f.x,h=f.attr?f.attr("y"):f.y,i=f.attr?f.attr("width"):f.width,j=f.attr?f.attr("height"):f.height,k;if(this.hasDragged||d)o(c.axes,function(c){if(c.zoomEnabled&&q(c.min)&&(d||b[{xAxis:"zoomX",yAxis:"zoomY"}[c.coll]])){var f=c.horiz,n=a.type==="touchend"?c.minPixelPadding:0,v=c.toValue((f?g:h)+n),f=c.toValue((f?g+i:h+j)-n);e[c.coll].push({axis:c,min:C(v,f),max:u(v,f)});k=!0}}),k&&I(c,"selection",e,function(a){c.zoom(x(a,d?{animation:!1}:null))});this.selectionMarker=this.selectionMarker.destroy();
-d&&this.scaleGroups()}if(c)L(c.container,{cursor:c._cursor}),c.cancelClick=this.hasDragged>10,c.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[]},onContainerMouseDown:function(a){a=this.normalize(a);a.preventDefault&&a.preventDefault();this.dragStart(a)},onDocumentMouseUp:function(a){Y[pa]&&Y[pa].pointer.drop(a)},onDocumentMouseMove:function(a){var b=this.chart,c=this.chartPosition,a=this.normalize(a,c);c&&!this.inClass(a.target,"highcharts-tracker")&&!b.isInsidePlot(a.chartX-b.plotLeft,
-a.chartY-b.plotTop)&&this.reset()},onContainerMouseLeave:function(){var a=Y[pa];if(a)a.pointer.reset(),a.pointer.chartPosition=null},onContainerMouseMove:function(a){var b=this.chart;pa=b.index;a=this.normalize(a);a.returnValue=!1;b.mouseIsDown==="mousedown"&&this.drag(a);(this.inClass(a.target,"highcharts-tracker")||b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop))&&!b.openMenu&&this.runPointActions(a)},inClass:function(a,b){for(var c;a;){if(c=J(a,"class"))if(c.indexOf(b)!==-1)return!0;else if(c.indexOf("highcharts-container")!==
--1)return!1;a=a.parentNode}},onTrackerMouseOut:function(a){var b=this.chart.hoverSeries,c=(a=a.relatedTarget||a.toElement)&&a.point&&a.point.series;if(b&&!b.options.stickyTracking&&!this.inClass(a,"highcharts-tooltip")&&c!==b)b.onMouseOut()},onContainerClick:function(a){var b=this.chart,c=b.hoverPoint,d=b.plotLeft,e=b.plotTop,a=this.normalize(a);a.originalEvent=a;b.cancelClick||(c&&this.inClass(a.target,"highcharts-tracker")?(I(c.series,"click",x(a,{point:c})),b.hoverPoint&&c.firePointEvent("click",
-a)):(x(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-d,a.chartY-e)&&I(b,"click",a)))},setDOMEvents:function(){var a=this,b=a.chart.container;b.onmousedown=function(b){a.onContainerMouseDown(b)};b.onmousemove=function(b){a.onContainerMouseMove(b)};b.onclick=function(b){a.onContainerClick(b)};H(b,"mouseleave",a.onContainerMouseLeave);bb===1&&H(B,"mouseup",a.onDocumentMouseUp);if(ab)b.ontouchstart=function(b){a.onContainerTouchStart(b)},b.ontouchmove=function(b){a.onContainerTouchMove(b)},bb===1&&
-H(B,"touchend",a.onDocumentTouchEnd)},destroy:function(){var a;Z(this.chart.container,"mouseleave",this.onContainerMouseLeave);bb||(Z(B,"mouseup",this.onDocumentMouseUp),Z(B,"touchend",this.onDocumentTouchEnd));clearInterval(this.tooltipTimeout);for(a in this)this[a]=null}};x(A.Pointer.prototype,{pinchTranslate:function(a,b,c,d,e,f){(this.zoomHor||this.pinchHor)&&this.pinchTranslateDirection(!0,a,b,c,d,e,f);(this.zoomVert||this.pinchVert)&&this.pinchTranslateDirection(!1,a,b,c,d,e,f)},pinchTranslateDirection:function(a,
-b,c,d,e,f,g,h){var i=this.chart,j=a?"x":"y",k=a?"X":"Y",l="chart"+k,m=a?"width":"height",n=i["plot"+(a?"Left":"Top")],v,s,p=h||1,o=i.inverted,t=i.bounds[a?"h":"v"],w=b.length===1,q=b[0][l],u=c[0][l],r=!w&&b[1][l],y=!w&&c[1][l],x,c=function(){!w&&O(q-r)>20&&(p=h||O(u-y)/O(q-r));s=(n-u)/p+q;v=i["plot"+(a?"Width":"Height")]/p};c();b=s;bt.max&&(b=t.max-v,x=!0);x?(u-=0.8*(u-g[j][0]),w||(y-=0.8*(y-g[j][1])),c()):g[j]=[u,y];o||(f[j]=s-n,f[m]=v);f=o?1/p:p;e[m]=v;e[j]=b;d[o?a?"scaleY":
-"scaleX":"scale"+k]=p;d["translate"+k]=f*n+(u-f*q)},pinch:function(a){var b=this,c=b.chart,d=b.pinchDown,e=a.touches,f=e.length,g=b.lastValidTouch,h=b.hasZoom,i=b.selectionMarker,j={},k=f===1&&(b.inClass(a.target,"highcharts-tracker")&&c.runTrackerClick||b.runChartClick),l={};if(f>1)b.initiated=!0;h&&b.initiated&&!k&&a.preventDefault();Ua(e,function(a){return b.normalize(a)});if(a.type==="touchstart")o(e,function(a,b){d[b]={chartX:a.chartX,chartY:a.chartY}}),g.x=[d[0].chartX,d[1]&&d[1].chartX],g.y=
-[d[0].chartY,d[1]&&d[1].chartY],o(c.axes,function(a){if(a.zoomEnabled){var b=c.bounds[a.horiz?"h":"v"],d=a.minPixelPadding,e=a.toPixels(p(a.options.min,a.dataMin)),f=a.toPixels(p(a.options.max,a.dataMax)),g=C(e,f),e=u(e,f);b.min=C(a.pos,g-d);b.max=u(a.pos+a.len,e+d)}}),b.res=!0;else if(d.length){if(!i)b.selectionMarker=i=x({destroy:na},c.plotBox);b.pinchTranslate(d,e,j,i,l,g);b.hasPinched=h;b.scaleGroups(j,l);if(!h&&b.followTouchMove&&f===1)this.runPointActions(b.normalize(a));else if(b.res)b.res=
-!1,this.reset(!1,0)}},touch:function(a,b){var c=this.chart;pa=c.index;a.touches.length===1?(a=this.normalize(a),c.isInsidePlot(a.chartX-c.plotLeft,a.chartY-c.plotTop)&&!c.openMenu?(b&&this.runPointActions(a),this.pinch(a)):b&&this.reset()):a.touches.length===2&&this.pinch(a)},onContainerTouchStart:function(a){this.touch(a,!0)},onContainerTouchMove:function(a){this.touch(a)},onDocumentTouchEnd:function(a){Y[pa]&&Y[pa].pointer.drop(a)}});if(K.PointerEvent||K.MSPointerEvent){var wa={},Bb=!!K.PointerEvent,
-Xb=function(){var a,b=[];b.item=function(a){return this[a]};for(a in wa)wa.hasOwnProperty(a)&&b.push({pageX:wa[a].pageX,pageY:wa[a].pageY,target:wa[a].target});return b},Cb=function(a,b,c,d){a=a.originalEvent||a;if((a.pointerType==="touch"||a.pointerType===a.MSPOINTER_TYPE_TOUCH)&&Y[pa])d(a),d=Y[pa].pointer,d[b]({type:c,target:a.currentTarget,preventDefault:na,touches:Xb()})};x(Va.prototype,{onContainerPointerDown:function(a){Cb(a,"onContainerTouchStart","touchstart",function(a){wa[a.pointerId]={pageX:a.pageX,
-pageY:a.pageY,target:a.currentTarget}})},onContainerPointerMove:function(a){Cb(a,"onContainerTouchMove","touchmove",function(a){wa[a.pointerId]={pageX:a.pageX,pageY:a.pageY};if(!wa[a.pointerId].target)wa[a.pointerId].target=a.currentTarget})},onDocumentPointerUp:function(a){Cb(a,"onDocumentTouchEnd","touchend",function(a){delete wa[a.pointerId]})},batchMSEvents:function(a){a(this.chart.container,Bb?"pointerdown":"MSPointerDown",this.onContainerPointerDown);a(this.chart.container,Bb?"pointermove":
-"MSPointerMove",this.onContainerPointerMove);a(B,Bb?"pointerup":"MSPointerUp",this.onDocumentPointerUp)}});cb(Va.prototype,"init",function(a,b,c){a.call(this,b,c);this.hasZoom&&L(b.container,{"-ms-touch-action":P,"touch-action":P})});cb(Va.prototype,"setDOMEvents",function(a){a.apply(this);(this.hasZoom||this.followTouchMove)&&this.batchMSEvents(H)});cb(Va.prototype,"destroy",function(a){this.batchMSEvents(Z);a.call(this)})}var nb=A.Legend=function(a,b){this.init(a,b)};nb.prototype={init:function(a,
-b){var c=this,d=b.itemStyle,e=b.itemMarginTop||0;this.options=b;if(b.enabled)c.itemStyle=d,c.itemHiddenStyle=z(d,b.itemHiddenStyle),c.itemMarginTop=e,c.padding=d=p(b.padding,8),c.initialItemX=d,c.initialItemY=d-5,c.maxItemWidth=0,c.chart=a,c.itemHeight=0,c.symbolWidth=p(b.symbolWidth,16),c.pages=[],c.render(),H(c.chart,"endResize",function(){c.positionCheckboxes()})},colorizeItem:function(a,b){var c=this.options,d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,c=b?c.itemStyle.color:
-g,h=b?a.legendColor||a.color||"#CCC":g,g=a.options&&a.options.marker,i={fill:h},j;d&&d.css({fill:c,color:c});e&&e.attr({stroke:h});if(f){if(g&&f.isMarker)for(j in i.stroke=h,g=a.convertAttribs(g),g)d=g[j],d!==y&&(i[j]=d);f.attr(i)}},positionItem:function(a){var b=this.options,c=b.symbolPadding,b=!b.rtl,d=a._legendItemPos,e=d[0],d=d[1],f=a.checkbox;(a=a.legendGroup)&&a.element&&a.translate(b?e:this.legendWidth-e-2*c-4,d);if(f)f.x=e,f.y=d},destroyItem:function(a){var b=a.checkbox;o(["legendItem","legendLine",
-"legendSymbol","legendGroup"],function(b){a[b]&&(a[b]=a[b].destroy())});b&&Ra(a.checkbox)},destroy:function(){var a=this.group,b=this.box;if(b)this.box=b.destroy();if(a)this.group=a.destroy()},positionCheckboxes:function(a){var b=this.group.alignAttr,c,d=this.clipHeight||this.legendHeight;if(b)c=b.translateY,o(this.allItems,function(e){var f=e.checkbox,g;f&&(g=c+f.y+(a||0)+3,L(f,{left:b.translateX+e.checkboxOffset+f.x-20+"px",top:g+"px",display:g>c-6&&g(m||b.chartWidth-2*j-s-d.x))this.itemX=s,this.itemY+=v+this.lastLineHeight+n,this.lastLineHeight=0;this.maxItemWidth=u(this.maxItemWidth,f);this.lastItemY=v+this.itemY+n;this.lastLineHeight=u(g,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=f:(this.itemY+=v+g+n,this.lastLineHeight=g);this.offsetWidth=m||u((e?this.itemX-s-k:f)+j,this.offsetWidth)},getAllItems:function(){var a=[];o(this.chart.series,function(b){var c=b.options;if(p(c.showInLegend,!q(c.linkedTo)?
-y:!1,!0))a=a.concat(b.legendItems||(c.legendType==="point"?b.data:b))});return a},adjustMargins:function(a,b){var c=this.chart,d=this.options,e=d.align[0]+d.verticalAlign[0]+d.layout[0];this.display&&!d.floating&&o([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(f,g){f.test(e)&&!q(a[g])&&(c[jb[g]]=u(c[jb[g]],c.legend[(g+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][g]*d[g%2?"x":"y"]+p(d.margin,12)+b[g]))})},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.group,e,f,
-g,h,i=a.box,j=a.options,k=a.padding,l=j.borderWidth,m=j.backgroundColor;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;if(!d)a.group=d=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),a.scrollGroup=c.g().add(a.contentGroup);a.renderTitle();e=a.getAllItems();rb(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});j.reversed&&e.reverse();a.allItems=e;a.display=f=!!e.length;a.lastLineHeight=0;
-o(e,function(b){a.renderItem(b)});g=(j.width||a.offsetWidth)+k;h=a.lastItemY+a.lastLineHeight+a.titleHeight;h=a.handleOverflow(h);h+=k;if(l||m){if(i){if(g>0&&h>0)i[i.isNew?"attr":"animate"](i.crisp({width:g,height:h})),i.isNew=!1}else a.box=i=c.rect(0,0,g,h,j.borderRadius,l||0).attr({stroke:j.borderColor,"stroke-width":l||0,fill:m||P}).add(d).shadow(j.shadow),i.isNew=!0;i[f?"show":"hide"]()}a.legendWidth=g;a.legendHeight=h;o(e,function(b){a.positionItem(b)});f&&d.align(x({width:g,height:h},j),!0,
-"spacingBox");b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var b=this,c=this.chart,d=c.renderer,e=this.options,f=e.y,f=c.spacingBox.height+(e.verticalAlign==="top"?-f:f)-this.padding,g=e.maxHeight,h,i=this.clipRect,j=e.navigation,k=p(j.animation,!0),l=j.arrowSize||12,m=this.nav,n=this.pages,v=this.padding,s,q=this.allItems,N=function(a){i.attr({height:a});if(b.contentGroup.div)b.contentGroup.div.style.clip="rect("+v+"px,9999px,"+(v+a)+"px,0)"};e.layout==="horizontal"&&(f/=2);
-g&&(f=C(f,g));n.length=0;if(a>f){this.clipHeight=h=u(f-20-this.titleHeight-v,0);this.currentPage=p(this.currentPage,1);this.fullHeight=a;o(q,function(a,b){var c=a._legendItemPos[1],d=r(a.legendItem.getBBox().height),e=n.length;if(!e||c-n[e-1]>h&&(s||c)!==n[e-1])n.push(s||c),e++;b===q.length-1&&c+d-n[e-1]>h&&n.push(c);c!==s&&(s=c)});if(!i)i=b.clipRect=d.clipRect(0,v,9999,0),b.contentGroup.clip(i);N(h);if(!m)this.nav=m=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",0,0,l,l).on("click",
-function(){b.scroll(-1,k)}).add(m),this.pager=d.text("",15,10).css(j.style).add(m),this.down=d.symbol("triangle-down",0,0,l,l).on("click",function(){b.scroll(1,k)}).add(m);b.scroll(0);a=f}else if(m)N(c.chartHeight),m.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0;return a},scroll:function(a,b){var c=this.pages,d=c.length,e=this.currentPage+a,f=this.clipHeight,g=this.options.navigation,h=g.activeColor,g=g.inactiveColor,i=this.pager,j=this.padding;e>d&&(e=d);if(e>0)b!==y&&Sa(b,this.chart),
-this.nav.attr({translateX:j,translateY:f+this.padding+7+this.titleHeight,visibility:"visible"}),this.up.attr({fill:e===1?g:h}).css({cursor:e===1?"default":"pointer"}),i.attr({text:e+"/"+d}),this.down.attr({x:18+this.pager.getBBox().width,fill:e===d?g:h}).css({cursor:e===d?"default":"pointer"}),c=-c[e-1]+this.initialItemY,this.scrollGroup.animate({translateY:c}),this.currentPage=e,this.positionCheckboxes(c)}};Na=A.LegendSymbolMixin={drawRectangle:function(a,b){var c=a.options.symbolHeight||a.fontMetrics.f;
-b.legendSymbol=this.chart.renderer.rect(0,a.baseline-c+1,a.symbolWidth,c,a.options.symbolRadius||0).attr({zIndex:3}).add(b.legendGroup)},drawLineMarker:function(a){var b=this.options,c=b.marker,d;d=a.symbolWidth;var e=this.chart.renderer,f=this.legendGroup,a=a.baseline-r(a.fontMetrics.b*0.3),g;if(b.lineWidth){g={"stroke-width":b.lineWidth};if(b.dashStyle)g.dashstyle=b.dashStyle;this.legendLine=e.path(["M",0,a,"L",d,a]).attr(g).add(f)}if(c&&c.enabled!==!1)b=c.radius,this.legendSymbol=d=e.symbol(this.symbol,
-d/2-b,a-b,2*b,2*b).add(f),d.isMarker=!0}};(/Trident\/7\.0/.test(Ba)||La)&&cb(nb.prototype,"positionItem",function(a,b){var c=this,d=function(){b._legendItemPos&&a.call(c,b)};d();setTimeout(d)});F=A.Chart=function(){this.init.apply(this,arguments)};F.prototype={callbacks:[],init:function(a,b){var c,d=a.series;a.series=null;c=z(T,a);c.series=a.series=d;this.userOptions=a;d=c.chart;this.margin=this.splashArray("margin",d);this.spacing=this.splashArray("spacing",d);var e=d.events;this.bounds={h:{},v:{}};
-this.callback=b;this.isResizing=0;this.options=c;this.axes=[];this.series=[];this.hasCartesianSeries=d.showAxes;var f=this,g;f.index=Y.length;Y.push(f);bb++;d.reflow!==!1&&H(f,"load",function(){f.initReflow()});if(e)for(g in e)H(f,g,e[g]);f.xAxis=[];f.yAxis=[];f.animation=fa?!1:p(d.animation,!0);f.pointCount=f.colorCounter=f.symbolCounter=0;f.firstRender()},initSeries:function(a){var b=this.options.chart;(b=M[a.type||b.type||b.defaultSeriesType])||la(17,!0);b=new b;b.init(this,a);return b},isInsidePlot:function(a,
-b,c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},redraw:function(a){var b=this.axes,c=this.series,d=this.pointer,e=this.legend,f=this.isDirtyLegend,g,h,i=this.hasCartesianSeries,j=this.isDirtyBox,k=c.length,l=k,m=this.renderer,n=m.isHidden(),p=[];Sa(a,this);n&&this.cloneRenderTo();for(this.layOutTitles();l--;)if(a=c[l],a.options.stacking&&(g=!0,a.isDirty)){h=!0;break}if(h)for(l=k;l--;)if(a=c[l],a.options.stacking)a.isDirty=!0;o(c,function(a){a.isDirty&&a.options.legendType===
-"point"&&(a.updateTotals&&a.updateTotals(),f=!0)});if(f&&e.options.enabled)e.render(),this.isDirtyLegend=!1;g&&this.getStacks();if(i&&!this.isResizing)this.maxTicks=null,o(b,function(a){a.setScale()});this.getMargins();i&&(o(b,function(a){a.isDirty&&(j=!0)}),o(b,function(a){if(a.isDirtyExtremes)a.isDirtyExtremes=!1,p.push(function(){I(a,"afterSetExtremes",x(a.eventArgs,a.getExtremes()));delete a.eventArgs});(j||g)&&a.redraw()}));j&&this.drawChartBox();o(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||
-a.xAxis)&&a.redraw()});d&&d.reset(!0);m.draw();I(this,"redraw");n&&this.cloneRenderTo(!0);o(p,function(a){a.call()})},get:function(a){var b=this.axes,c=this.series,d,e;for(d=0;d19?this.containerHeight:400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),Ra(b),delete this.renderToClone):(c&&
-c.parentNode===this.renderTo&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0),L(b,{position:"absolute",top:"-9999px",display:"block"}),b.style.setProperty&&b.style.setProperty("display","block","important"),B.body.appendChild(b),c&&b.appendChild(c))},getContainer:function(){var a,b=this.options.chart,c,d,e;this.renderTo=a=b.renderTo;e="highcharts-"+yb++;if(Da(a))this.renderTo=a=B.getElementById(a);a||la(13,!0);c=D(J(a,"data-highcharts-chart"));!isNaN(c)&&Y[c]&&Y[c].hasRendered&&
-Y[c].destroy();J(a,"data-highcharts-chart",this.index);a.innerHTML="";!b.skipClone&&!a.offsetWidth&&this.cloneRenderTo();this.getChartSize();c=this.chartWidth;d=this.chartHeight;this.container=a=$(Ka,{className:"highcharts-container"+(b.className?" "+b.className:""),id:e},x({position:"relative",overflow:"hidden",width:c+"px",height:d+"px",textAlign:"left",lineHeight:"normal",zIndex:0,"-webkit-tap-highlight-color":"rgba(0,0,0,0)"},b.style),this.renderToClone||a);this._cursor=a.style.cursor;this.renderer=
-b.forExport?new ua(a,c,d,b.style,!0):new $a(a,c,d,b.style);fa&&this.renderer.create(this,a,c,d);this.renderer.chartIndex=this.index},getMargins:function(a){var b=this.spacing,c=this.margin,d=this.titleOffset;this.resetMargins();if(d&&!q(c[0]))this.plotTop=u(this.plotTop,d+this.options.title.margin+b[0]);this.legend.adjustMargins(c,b);this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin);this.extraTopMargin&&(this.plotTop+=this.extraTopMargin);a||this.getAxisMargins()},getAxisMargins:function(){var a=
-this,b=a.axisOffset=[0,0,0,0],c=a.margin;a.hasCartesianSeries&&o(a.axes,function(a){a.getOffset()});o(jb,function(d,e){q(c[e])||(a[d]+=b[e])});a.setChartSize()},reflow:function(a){var b=this,c=b.options.chart,d=b.renderTo,e=c.width||kb(d,"width"),f=c.height||kb(d,"height"),c=a?a.target:K,d=function(){if(b.container)b.setSize(e,f,!1),b.hasUserSize=null};if(!b.hasUserSize&&!b.isPrinting&&e&&f&&(c===K||c===B)){if(e!==b.containerWidth||f!==b.containerHeight)clearTimeout(b.reflowTimeout),a?b.reflowTimeout=
-setTimeout(d,100):d();b.containerWidth=e;b.containerHeight=f}},initReflow:function(){var a=this,b=function(b){a.reflow(b)};H(K,"resize",b);H(a,"destroy",function(){Z(K,"resize",b)})},setSize:function(a,b,c){var d=this,e,f,g;d.isResizing+=1;g=function(){d&&I(d,"endResize",null,function(){d.isResizing-=1})};Sa(c,d);d.oldChartHeight=d.chartHeight;d.oldChartWidth=d.chartWidth;if(q(a))d.chartWidth=e=u(0,r(a)),d.hasUserSize=!!e;if(q(b))d.chartHeight=f=u(0,r(b));(za?mb:L)(d.container,{width:e+"px",height:f+
-"px"},za);d.setChartSize(!0);d.renderer.setSize(e,f,c);d.maxTicks=null;o(d.axes,function(a){a.isDirty=!0;a.setScale()});o(d.series,function(a){a.isDirty=!0});d.isDirtyLegend=!0;d.isDirtyBox=!0;d.layOutTitles();d.getMargins();d.redraw(c);d.oldChartHeight=null;I(d,"resize");za===!1?g():setTimeout(g,za&&za.duration||500)},setChartSize:function(a){var b=this.inverted,c=this.renderer,d=this.chartWidth,e=this.chartHeight,f=this.options.chart,g=this.spacing,h=this.clipOffset,i,j,k,l;this.plotLeft=i=r(this.plotLeft);
-this.plotTop=j=r(this.plotTop);this.plotWidth=k=u(0,r(d-i-this.marginRight));this.plotHeight=l=u(0,r(e-j-this.marginBottom));this.plotSizeX=b?l:k;this.plotSizeY=b?k:l;this.plotBorderWidth=f.plotBorderWidth||0;this.spacingBox=c.spacingBox={x:g[3],y:g[0],width:d-g[3]-g[1],height:e-g[0]-g[2]};this.plotBox=c.plotBox={x:i,y:j,width:k,height:l};d=2*V(this.plotBorderWidth/2);b=ta(u(d,h[3])/2);c=ta(u(d,h[0])/2);this.clipBox={x:b,y:c,width:V(this.plotSizeX-u(d,h[1])/2-b),height:u(0,V(this.plotSizeY-u(d,h[2])/
-2-c))};a||o(this.axes,function(a){a.setAxisSize();a.setAxisTranslation()})},resetMargins:function(){var a=this;o(jb,function(b,c){a[b]=p(a.margin[c],a.spacing[c])});a.axisOffset=[0,0,0,0];a.clipOffset=[0,0,0,0]},drawChartBox:function(){var a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,j=a.backgroundColor,k=a.plotBackgroundColor,l=a.plotBackgroundImage,m=a.plotBorderWidth||
-0,n,p=this.plotLeft,o=this.plotTop,q=this.plotWidth,u=this.plotHeight,t=this.plotBox,w=this.clipRect,r=this.clipBox;n=i+(a.shadow?8:0);if(i||j)if(e)e.animate(e.crisp({width:c-n,height:d-n}));else{e={fill:j||P};if(i)e.stroke=a.borderColor,e["stroke-width"]=i;this.chartBackground=b.rect(n/2,n/2,c-n,d-n,a.borderRadius,i).attr(e).addClass("highcharts-background").add().shadow(a.shadow)}if(k)f?f.animate(t):this.plotBackground=b.rect(p,o,q,u,0).attr({fill:k}).add().shadow(a.plotShadow);if(l)h?h.animate(t):
-this.plotBGImage=b.image(l,p,o,q,u).add();w?w.animate({width:r.width,height:r.height}):this.clipRect=b.clipRect(r);if(m)g?g.animate(g.crisp({x:p,y:o,width:q,height:u,strokeWidth:-m})):this.plotBorder=b.rect(p,o,q,u,0,-m).attr({stroke:a.plotBorderColor,"stroke-width":m,fill:P,zIndex:1}).add();this.isDirtyBox=!1},propFromSeries:function(){var a=this,b=a.options.chart,c,d=a.options.series,e,f;o(["inverted","angular","polar"],function(g){c=M[b.type||b.defaultSeriesType];f=a[g]||b[g]||c&&c.prototype[g];
-for(e=d&&d.length;!f&&e--;)(c=M[d[e].type])&&c.prototype[g]&&(f=!0);a[g]=f})},linkSeries:function(){var a=this,b=a.series;o(b,function(a){a.linkedSeries.length=0});o(b,function(b){var d=b.options.linkedTo;if(Da(d)&&(d=d===":previous"?a.series[b.index-1]:a.get(d)))d.linkedSeries.push(b),b.linkedParent=d})},renderSeries:function(){o(this.series,function(a){a.translate();a.render()})},renderLabels:function(){var a=this,b=a.options.labels;b.items&&o(b.items,function(c){var d=x(b.style,c.style),e=D(d.left)+
-a.plotLeft,f=D(d.top)+a.plotTop+12;delete d.left;delete d.top;a.renderer.text(c.html,e,f).attr({zIndex:2}).css(d).add()})},render:function(){var a=this.axes,b=this.renderer,c=this.options,d,e,f,g;this.setTitle();this.legend=new nb(this,c.legend);this.getStacks();this.getMargins(!0);this.setChartSize();d=this.plotWidth;e=this.plotHeight-=13;o(a,function(a){a.setScale()});this.getAxisMargins();f=d/this.plotWidth>1.1;g=e/this.plotHeight>1.1;if(f||g)this.maxTicks=null,o(a,function(a){(a.horiz&&f||!a.horiz&&
-g)&&a.setTickInterval(!0)}),this.getMargins();this.drawChartBox();this.hasCartesianSeries&&o(a,function(a){a.render()});if(!this.seriesGroup)this.seriesGroup=b.g("series-group").attr({zIndex:3}).add();this.renderSeries();this.renderLabels();this.showCredits(c.credits);this.hasRendered=!0},showCredits:function(a){if(a.enabled&&!this.credits)this.credits=this.renderer.text(a.text,0,0).on("click",function(){if(a.href)location.href=a.href}).attr({align:a.position.align,zIndex:8}).css(a.style).add().align(a.position)},
-destroy:function(){var a=this,b=a.axes,c=a.series,d=a.container,e,f=d&&d.parentNode;I(a,"destroy");Y[a.index]=y;bb--;a.renderTo.removeAttribute("data-highcharts-chart");Z(a);for(e=b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=c[e].destroy();o("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,pointer,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","),function(b){var c=a[b];c&&c.destroy&&(a[b]=c.destroy())});if(d)d.innerHTML=
-"",Z(d),f&&Ra(d);for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!ca&&K==K.top&&B.readyState!=="complete"||fa&&!K.canvg?(fa?Mb.push(function(){a.firstRender()},a.options.global.canvasToolsURL):B.attachEvent("onreadystatechange",function(){B.detachEvent("onreadystatechange",a.firstRender);B.readyState==="complete"&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options,c=a.callback;if(a.isReadyToRender()){a.getContainer();I(a,"init");a.resetMargins();a.setChartSize();
-a.propFromSeries();a.getAxes();o(b.series||[],function(b){a.initSeries(b)});a.linkSeries();I(a,"beforeRender");if(A.Pointer)a.pointer=new Va(a,b);a.render();a.renderer.draw();c&&c.apply(a,[a]);o(a.callbacks,function(b){a.index!==y&&b.apply(a,[a])});I(a,"load");a.cloneRenderTo(!0)}},splashArray:function(a,b){var c=b[a],c=da(c)?c:[c,c,c,c];return[p(b[a+"Top"],c[0]),p(b[a+"Right"],c[1]),p(b[a+"Bottom"],c[2]),p(b[a+"Left"],c[3])]}};var Yb=A.CenteredSeriesMixin={getCenter:function(){var a=this.options,
-b=this.chart,c=2*(a.slicedOffset||0),d=b.plotWidth-2*c,b=b.plotHeight-2*c,e=a.center,e=[p(e[0],"50%"),p(e[1],"50%"),a.size||"100%",a.innerSize||0],f=C(d,b),g,h;for(g=0;g<4;++g)h=e[g],a=g<2||g===2&&/%$/.test(h),e[g]=(/%$/.test(h)?[d,b,f,e[2]][g]*parseFloat(h)/100:parseFloat(h))+(a?c:0);return e}},Ga=function(){};Ga.prototype={init:function(a,b,c){this.series=a;this.color=a.color;this.applyOptions(b,c);this.pointAttr={};if(a.options.colorByPoint&&(b=a.options.colors||a.chart.options.colors,this.color=
-this.color||b[a.colorCounter++],a.colorCounter===b.length))a.colorCounter=0;a.chart.pointCount++;return this},applyOptions:function(a,b){var c=this.series,d=c.options.pointValKey||c.pointValKey,a=Ga.prototype.optionsToObject.call(this,a);x(this,a);this.options=this.options?x(this.options,a):a;if(d)this.y=this[d];if(this.x===y&&c)this.x=b===y?c.autoIncrement():b;return this},optionsToObject:function(a){var b={},c=this.series,d=c.options.keys,e=d||c.pointArrayMap||["y"],f=e.length,g=0,h=0;if(typeof a===
-"number"||a===null)b[e[0]]=a;else if(Ha(a)){if(!d&&a.length>f){c=typeof a[0];if(c==="string")b.name=a[0];else if(c==="number")b.x=a[0];g++}for(;ha+1&&b.push(d.slice(a+1,g)),a=g):g===e-1&&
-b.push(d.slice(a+1,g+1))});this.segments=b},setOptions:function(a){var b=this.chart,c=b.options.plotOptions,b=b.userOptions||{},d=b.plotOptions||{},e=c[this.type];this.userOptions=a;c=z(e,c.series,a);this.tooltipOptions=z(T.tooltip,T.plotOptions[this.type].tooltip,b.tooltip,d.series&&d.series.tooltip,d[this.type]&&d[this.type].tooltip,a.tooltip);e.marker===null&&delete c.marker;this.zoneAxis=c.zoneAxis;a=this.zones=(c.zones||[]).slice();if((c.negativeColor||c.negativeFillColor)&&!c.zones)a.push({value:c[this.zoneAxis+
-"Threshold"]||c.threshold||0,color:c.negativeColor,fillColor:c.negativeFillColor});a.length&&q(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return c},getCyclic:function(a,b,c){var d=this.userOptions,e="_"+a+"Index",f=a+"Counter";b||(q(d[e])?b=d[e]:(d[e]=b=this.chart[f]%c.length,this.chart[f]+=1),b=c[b]);this[a]=b},getColor:function(){this.options.colorByPoint||this.getCyclic("color",this.options.color||ba[this.type].color,this.chart.options.colors)},getSymbol:function(){var a=
-this.options.marker;this.getCyclic("symbol",a.symbol,this.chart.options.symbols);if(/^url/.test(this.symbol))a.radius=0},drawLegendSymbol:Na.drawLineMarker,setData:function(a,b,c,d){var e=this,f=e.points,g=f&&f.length||0,h,i=e.options,j=e.chart,k=null,l=e.xAxis,m=l&&!!l.categories,n=i.turboThreshold,v=this.xData,s=this.yData,q=(h=e.pointArrayMap)&&h.length,a=a||[];h=a.length;b=p(b,!0);if(d!==!1&&h&&g===h&&!e.cropped&&!e.hasGroupedData&&e.visible)o(a,function(a,b){f[b].update&&f[b].update(a,!1,null,
-!1)});else{e.xIncrement=null;e.pointRange=m?1:i.pointRange;e.colorCounter=0;o(this.parallelArrays,function(a){e[a+"Data"].length=0});if(n&&h>n){for(c=0;k===null&&ci||this.forceCrop))if(b[d-1]m)b=[],c=[];else if(b[0]m)e=this.cropData(this.xData,this.yData,l,m),b=e.xData,c=e.yData,e=e.start,f=!0;for(i=b.length-1;i>=0;i--)d=b[i]-b[i-1],d>0&&(g===y||d=c){f=u(0,i-h);break}for(;id){g=i+h;break}return{xData:a.slice(f,g),yData:b.slice(f,g),start:f,end:g}},generatePoints:function(){var a=this.options.data,b=this.data,c,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,i,j=this.hasGroupedData,k,l=[],m;if(!b&&!j)b=[],b.length=a.length,b=this.data=b;for(m=0;m0),j=this.getExtremesFromAll||this.options.getExtremesFromAll||this.cropped||
-(c[l+1]||j)>=g&&(c[l-1]||j)<=h,i&&j)if(i=k.length)for(;i--;)k[i]!==null&&(e[f++]=k[i]);else e[f++]=k;this.dataMin=Pa(e);this.dataMax=Fa(e)},translate:function(){this.processedXData||this.processData();this.generatePoints();for(var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,e=this.yAxis,f=this.points,g=f.length,h=!!this.modifyValue,i=a.pointPlacement,j=i==="between"||ra(i),k=a.threshold,l=a.startFromThreshold?k:0,m,n,v,o=Number.MAX_VALUE,a=0;a=0&&n<=e.len&&m>=0&&m<=c.len;r.clientX=j?c.translate(x,0,0,0,1):m;r.negative=r.y<(k||0);r.category=d&&d[r.x]!==y?d[r.x]:r.x;a&&(o=C(o,O(m-v)));v=m}this.closestPointRangePx=o;this.getSegments()},setClip:function(a){var b=this.chart,c=b.renderer,d=b.inverted,e=this.clipBox,f=e||b.clipBox,g=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,f.height].join(","),h=b[g],i=b[g+"m"];if(!h){if(a)f.width=
-0,b[g+"m"]=i=c.clipRect(-99,d?-b.plotLeft:-b.plotTop,99,d?b.chartWidth:b.chartHeight);b[g]=h=c.clipRect(f)}a&&(h.count+=1);if(this.options.clip!==!1)this.group.clip(a||e?h:b.clipRect),this.markerGroup.clip(i),this.sharedClipKey=g;a||(h.count-=1,h.count<=0&&g&&b[g]&&(e||(b[g]=b[g].destroy()),b[g+"m"]&&(b[g+"m"]=b[g+"m"].destroy())))},animate:function(a){var b=this.chart,c=this.options.animation,d;if(c&&!da(c))c=ba[this.type].animation;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX},
-c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99},c),this.animate=null)},afterAnimate:function(){this.setClip();I(this,"afterAnimate")},drawPoints:function(){var a,b=this.points,c=this.chart,d,e,f,g,h,i,j,k,l=this.options.marker,m=this.pointAttr[""],n,v,o,r=this.markerGroup,q=p(l.enabled,this.xAxis.isRadial,this.closestPointRangePx>2*l.radius);if(l.enabled!==!1||this._hasPointMarkers)for(f=b.length;f--;)if(g=b[f],d=V(g.plotX),e=g.plotY,k=g.graphic,n=g.marker||{},v=!!g.marker,a=q&&n.enabled===y||
-n.enabled,o=g.isInside,a&&e!==y&&!isNaN(e)&&g.y!==null)if(a=g.pointAttr[g.selected?"select":""]||m,h=a.r,i=p(n.symbol,this.symbol),j=i.indexOf("url")===0,k)k[o?"show":"hide"](!0).animate(x({x:d-h,y:e-h},k.symbolName?{width:2*h,height:2*h}:{}));else{if(o&&(h>0||j))g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h,v?n:l).attr(a).add(r)}else if(k)g.graphic=k.destroy()},convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,f,g,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=p(a[g],b[f],
-c[f],d[f]);return h},getAttribs:function(){var a=this,b=a.options,c=ba[a.type].marker?b.marker:b,d=c.states,e=d.hover,f,g=a.color,h=a.options.negativeColor;f={stroke:g,fill:g};var i=a.points||[],j,k=[],l,m=a.pointAttrToOptions;l=a.hasPointSpecificOptions;var n=c.lineColor,p=c.fillColor;j=b.turboThreshold;var s=a.zones,r=a.zoneAxis||"y",u;b.marker?(e.radius=e.radius||c.radius+e.radiusPlus,e.lineWidth=e.lineWidth||c.lineWidth+e.lineWidthPlus):(e.color=e.color||oa(e.color||g).brighten(e.brightness).get(),
-e.negativeColor=e.negativeColor||oa(e.negativeColor||h).brighten(e.brightness).get());k[""]=a.convertAttribs(c,f);o(["hover","select"],function(b){k[b]=a.convertAttribs(d[b],k[""])});a.pointAttr=k;g=i.length;if(!j||g=f.value;)f=s[++l];j.color=j.fillColor=f.color}l=b.colorByPoint||j.color;if(j.options)for(u in m)q(c[m[u]])&&(l=!0);if(l){c=c||{};l=[];d=c.states||{};f=d.hover=
-d.hover||{};if(!b.marker)f.color=f.color||!j.options.color&&e[j.negative&&h?"negativeColor":"color"]||oa(j.color).brighten(f.brightness||e.brightness).get();f={color:j.color};if(!p)f.fillColor=j.color;if(!n)f.lineColor=j.color;c.hasOwnProperty("color")&&!c.color&&delete c.color;l[""]=a.convertAttribs(x(f,c),k[""]);l.hover=a.convertAttribs(d.hover,k.hover,l[""]);l.select=a.convertAttribs(d.select,k.select,l[""])}else l=k;j.pointAttr=l}},destroy:function(){var a=this,b=a.chart,c=/AppleWebKit\/533/.test(Ba),
-d,e=a.data||[],f,g,h;I(a,"destroy");Z(a);o(a.axisTypes||[],function(b){if(h=a[b])ja(h.series,a),h.isDirty=h.forceRedraw=!0});a.legendItem&&a.chart.legend.destroyItem(a);for(d=e.length;d--;)(f=e[d])&&f.destroy&&f.destroy();a.points=null;clearTimeout(a.animationTimeout);for(g in a)a[g]instanceof Q&&!a[g].survive&&(d=c&&g==="group"?"hide":"destroy",a[g][d]());if(b.hoverSeries===a)b.hoverSeries=null;ja(b.series,a);for(g in a)delete a[g]},getSegmentPath:function(a){var b=this,c=[],d=b.options.step;o(a,
-function(e,f){var g=e.plotX,h=e.plotY,i;b.getPointSpline?c.push.apply(c,b.getPointSpline(a,e,f)):(c.push(f?"L":"M"),d&&f&&(i=a[f-1],d==="right"?c.push(i.plotX,h):d==="center"?c.push((i.plotX+g)/2,i.plotY,(i.plotX+g)/2,h):c.push(g,i.plotY)),c.push(e.plotX,e.plotY))});return c},getGraphPath:function(){var a=this,b=[],c,d=[];o(a.segments,function(e){c=a.getSegmentPath(e);e.length>1?b=b.concat(c):d.push(e[0])});a.singlePoints=d;return a.graphPath=b},drawGraph:function(){var a=this,b=this.options,c=[["graph",
-b.lineColor||this.color,b.dashStyle]],d=b.lineWidth,e=b.linecap!=="square",f=this.getGraphPath(),g=this.fillGraph&&this.color||P;o(this.zones,function(d,e){c.push(["zoneGraph"+e,d.color||a.color,d.dashStyle||b.dashStyle])});o(c,function(c,i){var j=c[0],k=a[j];if(k)db(k),k.animate({d:f});else if((d||g)&&f.length)k={stroke:c[1],"stroke-width":d,fill:g,zIndex:1},c[2]?k.dashstyle=c[2]:e&&(k["stroke-linecap"]=k["stroke-linejoin"]="round"),a[j]=a.chart.renderer.path(f).attr(k).add(a.group).shadow(i<2&&
-b.shadow)})},applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,f,g=this.clips||[],h,i=this.graph,j=this.area,k=u(b.chartWidth,b.chartHeight),l=this[(this.zoneAxis||"y")+"Axis"],m,n=l.reversed,v=b.inverted,s=l.horiz,q,x,t,w=!1;if(d.length&&(i||j))i&&i.hide(),j&&j.hide(),m=l.getExtremes(),o(d,function(d,o){e=n?s?b.plotWidth:0:s?0:l.toPixels(m.min);e=C(u(p(f,e),0),k);f=C(u(r(l.toPixels(p(d.value,m.max),!0)),0),k);w&&(e=f=l.toPixels(m.max));q=Math.abs(e-f);x=C(e,f);t=u(e,f);if(l.isXAxis){if(h=
-{x:v?t:x,y:0,width:q,height:k},!s)h.x=b.plotHeight-h.x}else if(h={x:0,y:v?t:x,width:k,height:q},s)h.y=b.plotWidth-h.y;b.inverted&&c.isVML&&(h=l.isXAxis?{x:0,y:n?x:t,height:h.width,width:b.chartWidth}:{x:h.y-b.plotLeft-b.spacingBox.x,y:0,width:h.height,height:b.chartHeight});g[o]?g[o].animate(h):(g[o]=c.clipRect(h),i&&a["zoneGraph"+o].clip(g[o]),j&&a["zoneArea"+o].clip(g[o]));w=d.value>m.max}),this.clips=g},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};o(["group",
-"markerGroup"],function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;if(b.xAxis)H(c,"resize",a),H(b,"destroy",function(){Z(c,"resize",a)}),a(),b.invertGroups=a},plotGroup:function(a,b,c,d,e){var f=this[a],g=!f;g&&(this[a]=f=this.chart.renderer.g(b).attr({visibility:c,zIndex:d||0.1}).add(e));f[g?"attr":"animate"](this.getPlotBox());return f},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;if(a.inverted)b=c,c=this.xAxis;return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:
-a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=(c=d.animation)&&!!a.animate&&b.renderer.isSVG&&p(c.duration,500)||0,f=a.visible?"visible":"hidden",g=d.zIndex,h=a.hasRendered,i=b.seriesGroup;c=a.plotGroup("group","series",f,g,i);a.markerGroup=a.plotGroup("markerGroup","markers",f,g,i);e&&a.animate(!0);a.getAttribs();c.inverted=a.isCartesian?b.inverted:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());o(a.points,function(a){a.redraw&&a.redraw()});a.drawDataLabels&&
-a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&a.options.enableMouseTracking!==!1&&a.drawTracker();b.inverted&&a.invertGroups();d.clip!==!1&&!a.sharedClipKey&&!h&&c.clip(b.clipRect);e&&a.animate();if(!h)e?a.animationTimeout=setTimeout(function(){a.afterAnimate()},e):a.afterAnimate();a.isDirty=a.isDirtyData=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,c=this.isDirty,d=this.group,e=this.xAxis,f=this.yAxis;d&&(a.inverted&&d.attr({width:a.plotWidth,height:a.plotHeight}),
-d.animate({translateX:p(e&&e.left,a.plotLeft),translateY:p(f&&f.top,a.plotTop)}));this.translate();this.render();b&&I(this,"updatedData");(c||b)&&delete this.kdTree},kdDimensions:1,kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,e=this.chart.inverted;return this.searchKDTree({clientX:e?c.len-a.chartY+c.pos:a.chartX-c.pos,plotY:e?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(b,d,g){var h,i;if(i=b&&b.length)return h=c.kdAxisArray[d%
-g],b.sort(function(a,b){return a[h]-b[h]}),i=Math.floor(i/2),{point:b[i],left:a(b.slice(0,i),d+1,g),right:a(b.slice(i+1),d+1,g)}}function b(){var b=lb(c.points,function(a){return a.y!==null});c.kdTree=a(b,d,d)}var c=this,d=c.kdDimensions;delete c.kdTree;c.options.kdSync?b():setTimeout(b)},searchKDTree:function(a,b){function c(a,b,j,k){var l=b.point,m=d.kdAxisArray[j%k],n,p,o=l;p=q(a[e])&&q(l[e])?Math.pow(a[e]-l[e],2):null;n=q(a[f])&&q(l[f])?Math.pow(a[f]-l[f],2):null;n=(p||0)+(n||0);l.dist=q(n)?Math.sqrt(n):
-Number.MAX_VALUE;l.distX=q(p)?Math.sqrt(p):Number.MAX_VALUE;m=a[m]-l[m];n=m<0?"left":"right";p=m<0?"right":"left";b[n]&&(n=c(a,b[n],j+1,k),o=n[g]m;)d--;e.updateParallelArrays(i,"splice",d,0,0);e.updateParallelArrays(i,d);if(k&&i.name)k[m]=i.name;h.splice(d,0,a);n&&(e.data.splice(d,0,null),e.processData());f.legendType==="point"&&e.generatePoints();c&&(g[0]&&g[0].remove?g[0].remove(!1):(g.shift(),e.updateParallelArrays(i,"shift"),h.shift()));e.isDirty=!0;e.isDirtyData=!0;b&&(e.getAttribs(),
-j.redraw())},removePoint:function(a,b,c){var d=this,e=d.data,f=e[a],g=d.points,h=d.chart,i=function(){e.length===g.length&&g.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(f||{series:d},"splice",a,1);f&&f.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&h.redraw()};Sa(c,h);b=p(b,!0);f?f.firePointEvent("remove",null,i):i()},remove:function(a,b){var c=this,d=c.chart,a=p(a,!0);if(!c.isRemoving)c.isRemoving=!0,I(c,"remove",null,function(){c.destroy();d.isDirtyLegend=d.isDirtyBox=
-!0;d.linkSeries();a&&d.redraw(b)});c.isRemoving=!1},update:function(a,b){var c=this,d=this.chart,e=this.userOptions,f=this.type,g=M[f].prototype,h=["group","markerGroup","dataLabelsGroup"],i;if(a.type&&a.type!==f||a.zIndex!==void 0)h.length=0;o(h,function(a){h[a]=c[a];delete c[a]});a=z(e,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data},a);this.remove(!1);for(i in g)this[i]=y;x(this,M[a.type||f].prototype);o(h,function(a){c[a]=h[a]});this.init(d,a);d.linkSeries();p(b,
-!0)&&d.redraw(!1)}});x(va.prototype,{update:function(a,b){var c=this.chart,a=c.options[this.coll][this.options.index]=z(this.userOptions,a);this.destroy(!0);this._addedPlotLB=this.chart._labelPanes=y;this.init(c,x(a,{events:y}));c.isDirtyBox=!0;p(b,!0)&&c.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,d=this.series,e=d.length;e--;)d[e]&&d[e].remove(!1);ja(b.axes,this);ja(b[c],this);b.options[c].splice(this.options.index,1);o(b[c],function(a,b){a.options.index=b});this.destroy();b.isDirtyBox=
-!0;p(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}});var xa=ka(R);M.line=xa;ba.area=z(U,{threshold:0});var qa=ka(R,{type:"area",getSegments:function(){var a=this,b=[],c=[],d=[],e=this.xAxis,f=this.yAxis,g=f.stacks[this.stackKey],h={},i,j,k=this.points,l=this.options.connectNulls,m,n;if(this.options.stacking&&!this.cropped){for(m=0;m=0;d--)g=p(a[d].yBottom,f),da&&i>e?(i=u(a,e),k=2*e-i):ig&&k>e?(k=u(g,e),i=2*e-k):kg?d-g:f-(x?g:0)));
-c.barX=o;c.pointWidth=i;q=r(o+q)+l;o=r(o)+l;q-=o;d=O(t)<0.5;w=C(r(t+w)+m,9E4);t=r(t)+m;w-=t;d&&(t-=1,w+=1);c.tooltipPos=b.inverted?[e.len+e.pos-b.plotLeft-h,a.xAxis.len-o-q/2,w]:[o+q/2,h+e.pos-b.plotTop,w];c.shapeType="rect";c.shapeArgs={x:o,y:t,width:q,height:w}})},getSymbol:na,drawLegendSymbol:Na.drawRectangle,drawGraph:na,drawPoints:function(){var a=this,b=this.chart,c=a.options,d=b.renderer,e=c.animationLimit||250,f,g;o(a.points,function(h){var i=h.plotY,j=h.graphic;if(i!==y&&!isNaN(i)&&h.y!==
-null)f=h.shapeArgs,i=q(a.borderWidth)?{"stroke-width":a.borderWidth}:{},g=h.pointAttr[h.selected?"select":""]||a.pointAttr[""],j?(db(j),j.attr(i)[b.pointCount\u25CF
{series.name}
',
-pointFormat:"x: {point.x}
y: {point.y}
"}});qa=ka(R,{type:"scatter",sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group","markerGroup","dataLabelsGroup"],takeOrdinalPosition:!1,kdDimensions:2,drawGraph:function(){this.options.lineWidth&&R.prototype.drawGraph.call(this)}});M.scatter=qa;ba.pie=z(U,{borderColor:"#FFFFFF",borderWidth:1,center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name},x:0},
-ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,states:{hover:{brightness:0.1,shadow:!1}},stickyTracking:!1,tooltip:{followPointer:!0}});U={type:"pie",isCartesian:!1,pointClass:ka(Ga,{init:function(){Ga.prototype.init.apply(this,arguments);var a=this,b;x(a,{visible:a.visible!==!1,name:p(a.name,"Slice")});b=function(b){a.slice(b.type==="select")};H(a,"select",b);H(a,"unselect",b);return a},setVisible:function(a,b){var c=this,d=c.series,e=d.chart,f=d.options.ignoreHiddenPoint,
-b=p(b,f);if(a!==c.visible){c.visible=c.options.visible=a=a===y?!c.visible:a;d.options.data[Ma(c,d.data)]=c.options;o(["graphic","dataLabel","connector","shadowGroup"],function(b){if(c[b])c[b][a?"show":"hide"](!0)});c.legendItem&&e.legend.colorizeItem(c,a);!a&&c.state==="hover"&&c.setState("");if(f)d.isDirty=!0;b&&e.redraw()}},slice:function(a,b,c){var d=this.series;Sa(c,d.chart);p(b,!0);this.sliced=this.options.sliced=a=q(a)?a:!this.sliced;d.options.data[Ma(this,d.data)]=this.options;a=a?this.slicedTranslation:
-{translateX:0,translateY:0};this.graphic.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)},haloPath:function(a){var b=this.shapeArgs,c=this.series.chart;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.plotLeft+b.x,c.plotTop+b.y,b.r+a,b.r+a,{innerR:this.shapeArgs.r,start:b.start,end:b.end})}}),requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",
-fill:"color"},getColor:na,animate:function(a){var b=this,c=b.points,d=b.startAngleRad;if(!a)o(c,function(a){var c=a.graphic,g=a.shapeArgs;c&&(c.attr({r:a.startR||b.center[3]/2,start:d,end:d}),c.animate({r:g.r,start:g.start,end:g.end},b.options.animation))}),b.animate=null},setData:function(a,b,c,d){R.prototype.setData.call(this,a,!1,c,d);this.processData();this.generatePoints();p(b,!0)&&this.chart.redraw(c)},updateTotals:function(){var a,b=0,c=this.points,d=c.length,e,f=this.options.ignoreHiddenPoint;
-for(a=0;a0&&(e.visible||!f)?e.y/b*100:0,e.total=b},generatePoints:function(){R.prototype.generatePoints.call(this);this.updateTotals()},translate:function(a){this.generatePoints();var b=0,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f,g,h,i=c.startAngle||0,j=this.startAngleRad=ma/180*(i-90),i=(this.endAngleRad=ma/180*(p(c.endAngle,i+360)-90))-j,k=this.points,l=c.dataLabels.distance,c=c.ignoreHiddenPoint,m,
-n=k.length,o;if(!a)this.center=a=this.getCenter();this.getX=function(b,c){h=W.asin(C((b-a[1])/(a[2]/2+l),1));return a[0]+(c?-1:1)*X(h)*(a[2]/2+l)};for(m=0;m1.5*ma?h-=2*ma:h<-ma/2&&(h+=2*ma);o.slicedTranslation={translateX:r(X(h)*d),translateY:r(aa(h)*d)};f=X(h)*a[2]/2;g=aa(h)*a[2]/2;o.tooltipPos=[a[0]+f*0.7,a[1]+g*
-0.7];o.half=h<-ma/2||h>ma/2?1:0;o.angle=h;e=C(e,l/2);o.labelPos=[a[0]+f+X(h)*l,a[1]+g+aa(h)*l,a[0]+f+X(h)*e,a[1]+g+aa(h)*e,a[0]+f,a[1]+g,l<0?"center":o.half?"right":"left",h]}},drawGraph:null,drawPoints:function(){var a=this,b=a.chart.renderer,c,d,e=a.options.shadow,f,g,h;if(e&&!a.shadowGroup)a.shadowGroup=b.g("shadow").add(a.group);o(a.points,function(i){d=i.graphic;g=i.shapeArgs;f=i.shadowGroup;if(e&&!f)f=i.shadowGroup=b.g("shadow").add(a.shadowGroup);c=i.sliced?i.slicedTranslation:{translateX:0,
-translateY:0};f&&f.attr(c);if(d)d.animate(x(g,c));else{h={"stroke-linejoin":"round"};if(!i.visible)h.visibility="hidden";i.graphic=d=b[i.shapeType](g).setRadialReference(a.center).attr(i.pointAttr[i.selected?"select":""]).attr(h).attr(c).add(a.group).shadow(e,f)}})},searchPoint:na,sortByAngle:function(a,b){a.sort(function(a,d){return a.angle!==void 0&&(d.angle-a.angle)*b})},drawLegendSymbol:Na.drawRectangle,getCenter:Yb.getCenter,getSymbol:na};U=ka(R,U);M.pie=U;R.prototype.drawDataLabels=function(){var a=
-this,b=a.options,c=b.cursor,d=b.dataLabels,e=a.points,f,g,h=a.hasRendered||0,i,j,k=a.chart.renderer;if(d.enabled||a._hasPointLabels)a.dlProcessOptions&&a.dlProcessOptions(d),j=a.plotGroup("dataLabelsGroup","data-labels",d.defer?"hidden":"visible",d.zIndex||6),p(d.defer,!0)&&(j.attr({opacity:+h}),h||H(a,"afterAnimate",function(){a.visible&&j.show();j[b.animation?"animate":"attr"]({opacity:1},{duration:200})})),g=d,o(e,function(e){var h,n=e.dataLabel,o,s,r=e.connector,u=!0,t,w={};f=e.dlOptions||e.options&&
-e.options.dataLabels;h=p(f&&f.enabled,g.enabled);if(n&&!h)e.dataLabel=n.destroy();else if(h){d=z(g,f);t=d.style;h=d.rotation;o=e.getLabelConfig();i=d.format?Ja(d.format,o):d.formatter.call(o,d);t.color=p(d.color,t.color,a.color,"black");if(n)if(q(i))n.attr({text:i}),u=!1;else{if(e.dataLabel=n=n.destroy(),r)e.connector=r.destroy()}else if(q(i)){n={fill:d.backgroundColor,stroke:d.borderColor,"stroke-width":d.borderWidth,r:d.borderRadius||0,rotation:h,padding:d.padding,zIndex:1};if(t.color==="contrast")w.color=
-d.inside||d.distance<0||b.stacking?k.getContrast(e.color||a.color):"#000000";if(c)w.cursor=c;for(s in n)n[s]===y&&delete n[s];n=e.dataLabel=k[h?"text":"label"](i,0,-999,d.shape,null,null,d.useHTML).attr(n).css(x(t,w)).add(j).shadow(d.shadow)}n&&a.alignDataLabel(e,n,d,null,u)}})};R.prototype.alignDataLabel=function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=p(a.plotX,-999),i=p(a.plotY,-999),j=b.getBBox(),k=f.renderer.fontMetrics(c.style.fontSize).b,l=this.visible&&(a.series.forceDL||f.isInsidePlot(h,
-r(i),g)||d&&f.isInsidePlot(h,g?d.x+1:d.y+d.height-1,g));if(l)d=x({x:g?f.plotWidth-i:h,y:r(g?f.plotHeight-h:i),width:0,height:0},d),x(c,{width:j.width,height:j.height}),c.rotation?(a=f.renderer.rotCorr(k,c.rotation),b[e?"attr":"animate"]({x:d.x+c.x+d.width/2+a.x,y:d.y+c.y+d.height/2}).attr({align:c.align})):(b.align(c,null,d),g=b.alignAttr,p(c.overflow,"justify")==="justify"?this.justifyDataLabel(b,c,g,j,d,e):p(c.crop,!0)&&(l=f.isInsidePlot(g.x,g.y)&&f.isInsidePlot(g.x+j.width,g.y+j.height)),c.shape&&
-b.attr({anchorX:a.plotX,anchorY:a.plotY}));if(!l)b.attr({y:-999}),b.placed=!1};R.prototype.justifyDataLabel=function(a,b,c,d,e,f){var g=this.chart,h=b.align,i=b.verticalAlign,j,k,l=a.box?0:a.padding||0;j=c.x+l;if(j<0)h==="right"?b.align="left":b.x=-j,k=!0;j=c.x+d.width-l;if(j>g.plotWidth)h==="left"?b.align="right":b.x=g.plotWidth-j,k=!0;j=c.y+l;if(j<0)i==="bottom"?b.verticalAlign="top":b.y=-j,k=!0;j=c.y+d.height-l;if(j>g.plotHeight)i==="top"?b.verticalAlign="bottom":b.y=g.plotHeight-j,k=!0;if(k)a.placed=
-!f,a.align(b,null,e)};if(M.pie)M.pie.prototype.drawDataLabels=function(){var a=this,b=a.data,c,d=a.chart,e=a.options.dataLabels,f=p(e.connectorPadding,10),g=p(e.connectorWidth,1),h=d.plotWidth,i=d.plotHeight,j,k,l=p(e.softConnector,!0),m=e.distance,n=a.center,q=n[2]/2,s=n[1],x=m>0,y,t,w,z=[[],[]],B,A,D,F,G,E=[0,0,0,0],L=function(a,b){return b.y-a.y};if(a.visible&&(e.enabled||a._hasPointLabels)){R.prototype.drawDataLabels.apply(a);o(b,function(a){a.dataLabel&&a.visible&&z[a.half].push(a)});for(F=2;F--;){var I=
-[],M=[],H=z[F],K=H.length,J;if(K){a.sortByAngle(H,F-0.5);for(G=b=0;!b&&H[G];)b=H[G]&&H[G].dataLabel&&(H[G].dataLabel.getBBox().height||21),G++;if(m>0){t=C(s+q+m,d.plotHeight);for(G=u(0,s-q-m);G<=t;G+=b)I.push(G);t=I.length;if(K>t){c=[].concat(H);c.sort(L);for(G=K;G--;)c[G].rank=G;for(G=K;G--;)H[G].rank>=t&&H.splice(G,1);K=H.length}for(G=0;G0){if(t=M.pop(),J=t.i,A=t.y,c>A&&I[J+1]!==null||ch-
-f&&(E[1]=u(r(B+t-h+f),E[1])),A-b/2<0?E[0]=u(r(-A+b/2),E[0]):A+b/2>i&&(E[2]=u(r(A+b/2-i),E[2]))}}}if(Fa(E)===0||this.verifyDataLabelOverflow(E))this.placeDataLabels(),x&&g&&o(this.points,function(b){j=b.connector;w=b.labelPos;if((y=b.dataLabel)&&y._pos&&b.visible)D=y._attr.visibility,B=y.connX,A=y.connY,k=l?["M",B+(w[6]==="left"?5:-5),A,"C",B,A,2*w[2]-w[4],2*w[3]-w[5],w[2],w[3],"L",w[4],w[5]]:["M",B+(w[6]==="left"?5:-5),A,"L",w[2],w[3],"L",w[4],w[5]],j?(j.animate({d:k}),j.attr("visibility",D)):b.connector=
-j=a.chart.renderer.path(k).attr({"stroke-width":g,stroke:e.connectorColor||b.color||"#606060",visibility:D}).add(a.dataLabelsGroup);else if(j)b.connector=j.destroy()})}},M.pie.prototype.placeDataLabels=function(){o(this.points,function(a){var b=a.dataLabel;if(b&&a.visible)(a=b._pos)?(b.attr(b._attr),b[b.moved?"animate":"attr"](a),b.moved=!0):b&&b.attr({y:-999})})},M.pie.prototype.alignDataLabel=na,M.pie.prototype.verifyDataLabelOverflow=function(a){var b=this.center,c=this.options,d=c.center,e=c.minSize||
-80,f=e,g;d[0]!==null?f=u(b[2]-u(a[1],a[3]),e):(f=u(b[2]-a[1]-a[3],e),b[0]+=(a[3]-a[1])/2);d[1]!==null?f=u(C(f,b[2]-u(a[0],a[2])),e):(f=u(C(f,b[2]-a[0]-a[2]),e),b[1]+=(a[0]-a[2])/2);fp(this.translatedThreshold,g.yAxis.len)),j=p(c.inside,!!this.options.stacking);if(h&&(d=z(h),f&&(d={x:g.yAxis.len-d.y-d.height,y:g.xAxis.len-d.x-d.width,width:d.height,height:d.width}),!j))f?(d.x+=i?0:d.width,d.width=0):(d.y+=i?d.height:0,d.height=0);c.align=p(c.align,!f||j?"center":i?"right":"left");c.verticalAlign=p(c.verticalAlign,f||j?"middle":i?"top":"bottom");R.prototype.alignDataLabel.call(this,a,b,c,d,e)};(function(a){var b=
-a.Chart,c=a.each,d=a.pick,e=HighchartsAdapter.addEvent;b.prototype.callbacks.push(function(a){function b(){var e=[];c(a.series,function(a){var b=a.options.dataLabels;(b.enabled||a._hasPointLabels)&&!b.allowOverlap&&a.visible&&c(a.points,function(a){if(a.dataLabel)a.dataLabel.labelrank=d(a.labelrank,a.shapeArgs&&a.shapeArgs.height),e.push(a.dataLabel)})});a.hideOverlappingLabels(e)}b();e(a,"redraw",b)});b.prototype.hideOverlappingLabels=function(a){var b=a.length,c,d,e,k;for(d=0;de.alignAttr.x+e.width||k.alignAttr.x+k.widthe.alignAttr.y+e.height||k.alignAttr.y+k.heightd;if(h.series.length&&(i||l>C(k.dataMin,k.min))&&(!i||js;s++)if(t.call(n,e[s],s,e)===c)return}else for(var i in e)if(u.has(e,i)&&t.call(n,e[i],i,e)===c)return};u.result=function(e,t){if(null==e)return null;var n=e[t];return u.isFunction(n)?n.call(e):n},u.once=function(e){var t,n=!1;return function(){return n?t:(n=!0,t=e.apply(this,arguments),e=null,t)}};var p=0;return u.uniqueId=function(e){var t=++p+"";return e?e+t:t},u.filter=u.select=function(e,t,n){var s=[];return null==e?s:i&&e.filter===i?e.filter(t,n):(h(e,function(e,r,o){t.call(n,e,r,o)&&(s[s.length]=e)}),s)},h(["Arguments","Function","String","Number","Date","RegExp"],function(e){u["is"+e]=function(t){return r.call(t)=="[object "+e+"]"}}),u.defaults=function(e){return h(s.call(arguments,1),function(t){if(t)for(var n in t)null==e[n]&&(e[n]=t[n])}),e},u.extend=function(e){return h(s.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},u.keys=a||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)u.has(e,n)&&(t[t.length]=n);return t},u.bind=function(e,t){if(e.bind===l&&l)return l.apply(e,s.call(arguments,1));var n=s.call(arguments,2);return function(){return e.apply(t,n.concat(s.call(arguments)))}},u.isObject=function(e){return e===Object(e)},u}(),window.Messenger.Events=function(){if(window.Backbone&&Backbone.Events)return Backbone.Events;var e=function(){var e=/\s+/,t=function(t,n,s,r){if(!s)return!0;if("object"==typeof s)for(var o in s)t[n].apply(t,[o,s[o]].concat(r));else{if(!e.test(s))return!0;for(var i=s.split(e),a=0,l=i.length;l>a;a++)t[n].apply(t,[i[a]].concat(r))}},n=function(e,t){var n,s=-1,r=e.length;switch(t.length){case 0:for(;r>++s;)(n=e[s]).callback.call(n.ctx);return;case 1:for(;r>++s;)(n=e[s]).callback.call(n.ctx,t[0]);return;case 2:for(;r>++s;)(n=e[s]).callback.call(n.ctx,t[0],t[1]);return;case 3:for(;r>++s;)(n=e[s]).callback.call(n.ctx,t[0],t[1],t[2]);return;default:for(;r>++s;)(n=e[s]).callback.apply(n.ctx,t)}},s={on:function(e,n,s){if(!t(this,"on",e,[n,s])||!n)return this;this._events||(this._events={});var r=this._events[e]||(this._events[e]=[]);return r.push({callback:n,context:s,ctx:s||this}),this},once:function(e,n,s){if(!t(this,"once",e,[n,s])||!n)return this;var r=this,o=_.once(function(){r.off(e,o),n.apply(this,arguments)});return o._callback=n,this.on(e,o,s),this},off:function(e,n,s){var r,o,i,a,l,u,c,h;if(!this._events||!t(this,"off",e,[n,s]))return this;if(!e&&!n&&!s)return this._events={},this;for(a=e?[e]:_.keys(this._events),l=0,u=a.length;u>l;l++)if(e=a[l],r=this._events[e]){if(i=[],n||s)for(c=0,h=r.length;h>c;c++)o=r[c],(n&&n!==o.callback&&n!==o.callback._callback||s&&s!==o.context)&&i.push(o);this._events[e]=i}return this},trigger:function(e){if(!this._events)return this;var s=Array.prototype.slice.call(arguments,1);if(!t(this,"trigger",e,s))return this;var r=this._events[e],o=this._events.all;return r&&n(r,s),o&&n(o,arguments),this},listenTo:function(e,t,n){var s=this._listeners||(this._listeners={}),r=e._listenerId||(e._listenerId=_.uniqueId("l"));return s[r]=e,e.on(t,"object"==typeof t?this:n,this),this},stopListening:function(e,t,n){var s=this._listeners;if(s){if(e)e.off(t,"object"==typeof t?this:n,this),t||n||delete s[e._listenerId];else{"object"==typeof t&&(n=this);for(var r in s)s[r].off(t,n,this);this._listeners={}}return this}}};return s.bind=s.on,s.unbind=s.off,s};return e()}(),function(){var e,t,n,s,r,o,i,a,l,u,c,h={}.hasOwnProperty,p=function(e,t){function n(){this.constructor=e}for(var s in t)h.call(t,s)&&(e[s]=t[s]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e},d=[].slice,f=[].indexOf||function(e){for(var t=0,n=this.length;n>t;t++)if(t in this&&this[t]===e)return t;return-1};e=jQuery,o=null!=(l=window._)?l:window.Messenger._,s=null!=(u="undefined"!=typeof Backbone&&null!==Backbone?Backbone.Events:void 0)?u:window.Messenger.Events,n=function(){function t(t){e.extend(this,s),o.isObject(t)&&(t.el&&this.setElement(t.el),this.model=t.model),this.initialize.apply(this,arguments)}return t.prototype.setElement=function(t){return this.$el=e(t),this.el=this.$el[0]},t.prototype.delegateEvents=function(e){var t,n,s,r,i,a,l;if(e||(e=o.result(this,"events"))){this.undelegateEvents(),t=/^(\S+)\s*(.*)$/,l=[];for(s in e){if(i=e[s],o.isFunction(i)||(i=this[e[s]]),!i)throw Error('Method "'+e[s]+'" does not exist');r=s.match(t),n=r[1],a=r[2],i=o.bind(i,this),n+=".delegateEvents"+this.cid,""===a?l.push(this.jqon(n,i)):l.push(this.jqon(n,a,i))}return l}},t.prototype.jqon=function(e,t,n){var s;return null!=this.$el.on?(s=this.$el).on.apply(s,arguments):(null==n&&(n=t,t=void 0),null!=t?this.$el.delegate(t,e,n):this.$el.bind(e,n))},t.prototype.jqoff=function(e){var t;return null!=this.$el.off?(t=this.$el).off.apply(t,arguments):(this.$el.undelegate(),this.$el.unbind(e))},t.prototype.undelegateEvents=function(){return this.jqoff(".delegateEvents"+this.cid)},t.prototype.remove=function(){return this.undelegateEvents(),this.$el.remove()},t}(),i=function(t){function n(){return n.__super__.constructor.apply(this,arguments)}return p(n,t),n.prototype.defaults={hideAfter:10,scroll:!0,closeButtonText:"×"},n.prototype.initialize=function(t){return null==t&&(t={}),this.shown=!1,this.rendered=!1,this.messenger=t.messenger,this.options=e.extend({},this.options,t,this.defaults)},n.prototype.show=function(){var e;return this.rendered||this.render(),this.$message.removeClass("messenger-hidden"),e=this.shown,this.shown=!0,e?void 0:this.trigger("show")},n.prototype.hide=function(){var e;if(this.rendered)return this.$message.addClass("messenger-hidden"),e=this.shown,this.shown=!1,e?this.trigger("hide"):void 0},n.prototype.cancel=function(){return this.hide()},n.prototype.update=function(t){var n,s=this;return o.isString(t)&&(t={message:t}),e.extend(this.options,t),this.lastUpdate=new Date,this.rendered=!1,this.events=null!=(n=this.options.events)?n:{},this.render(),this.actionsToEvents(),this.delegateEvents(),this.checkClickable(),this.options.hideAfter?(this.$message.addClass("messenger-will-hide-after"),null!=this._hideTimeout&&clearTimeout(this._hideTimeout),this._hideTimeout=setTimeout(function(){return s.hide()},1e3*this.options.hideAfter)):this.$message.removeClass("messenger-will-hide-after"),this.options.hideOnNavigate?(this.$message.addClass("messenger-will-hide-on-navigate"),null!=("undefined"!=typeof Backbone&&null!==Backbone?Backbone.history:void 0)&&Backbone.history.on("route",function(){return s.hide()})):this.$message.removeClass("messenger-will-hide-on-navigate"),this.trigger("update",this)},n.prototype.scrollTo=function(){return this.options.scroll?e.scrollTo(this.$el,{duration:400,offset:{left:0,top:-20}}):void 0},n.prototype.timeSinceUpdate=function(){return this.lastUpdate?new Date-this.lastUpdate:null},n.prototype.actionsToEvents=function(){var e,t,n,s,r=this;n=this.options.actions,s=[];for(t in n)e=n[t],s.push(this.events['click [data-action="'+t+'"] a']=function(e){return function(n){return n.preventDefault(),n.stopPropagation(),r.trigger("action:"+t,e,n),e.action.call(r,n,r)}}(e));return s},n.prototype.checkClickable=function(){var e,t,n,s;n=this.events,s=[];for(t in n)e=n[t],"click"===t?s.push(this.$message.addClass("messenger-clickable")):s.push(void 0);return s},n.prototype.undelegateEvents=function(){var e;return n.__super__.undelegateEvents.apply(this,arguments),null!=(e=this.$message)?e.removeClass("messenger-clickable"):void 0},n.prototype.parseActions=function(){var t,n,s,r,o,i;n=[],o=this.options.actions;for(r in o)t=o[r],s=e.extend({},t),s.name=r,null==(i=s.label)&&(s.label=r),n.push(s);return n},n.prototype.template=function(t){var n,s,r,o,i,a,l,u,c,h,p=this;for(i=e("