├── .gitignore ├── COPYING ├── README ├── Rakefile ├── app ├── controllers │ ├── application_controller.rb │ ├── card_controller.rb │ ├── juggernaut_sync_controller.rb │ ├── login_controller.rb │ ├── project_controller.rb │ └── taskboard_controller.rb ├── helpers │ ├── application_helper.rb │ ├── card_helper.rb │ ├── juggernaut_sync_helper.rb │ ├── login_helper.rb │ ├── project_helper.rb │ └── taskboard_helper.rb ├── models │ ├── card.rb │ ├── column.rb │ ├── hour.rb │ ├── project.rb │ ├── row.rb │ ├── taskboard.rb │ └── user.rb └── views │ ├── login │ ├── _user_meta.html.erb │ ├── add_user.html.erb │ ├── list_users.html.erb │ └── login.html.erb │ ├── project │ ├── _footer.html.erb │ ├── _project.html.erb │ └── index.html.erb │ └── taskboard │ ├── _taskboard.html.erb │ └── show.html.erb ├── config ├── boot.rb ├── database.example.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── inflections.rb │ ├── mime_types.rb │ ├── new_rails_defaults.rb │ └── require.rb ├── juggernaut.example.yml ├── juggernaut_hosts.example.yml ├── routes.rb └── taskboard.example.yml ├── db ├── migrate │ ├── 20081010142942_create_cards.rb │ ├── 20081013145250_create_taskboards.rb │ ├── 20081013170754_create_columns.rb │ ├── 20081031114623_foreign_keys.rb │ ├── 20081127152023_acts_as_taggable_migration.rb │ ├── 20081205134317_create_hours.rb │ ├── 20090317140555_create_sessions.rb │ ├── 20090428084605_create_users.rb │ ├── 20090428123003_add_default_users.rb │ ├── 20090706124829_create_rows.rb │ ├── 20090707130233_add_cards_to_rows.rb │ ├── 20090922095631_create_projects.rb │ └── 20090922100811_add_taskboards_to_projects.rb └── schema.rb ├── lib ├── jira_integration.rb ├── jira_parser.rb ├── migration_helpers.rb ├── taskboard_config.rb ├── taskboard_version.rb ├── url_parser.rb └── utils.rb ├── log └── report │ └── readme ├── public ├── 404.html ├── 422.html ├── 500.html ├── dispatch.cgi ├── dispatch.fcgi ├── dispatch.rb ├── favicon.ico ├── favicon.png ├── images │ ├── cognifide_logo.png │ ├── collapse_all.png │ ├── color_big_off.png │ ├── color_big_on.png │ ├── color_off.png │ ├── color_on.png │ ├── copy.png │ ├── cross_16.png │ ├── cross_off.png │ ├── cross_on.png │ ├── expand_all.png │ ├── hide_off.png │ ├── hide_on.png │ ├── jquery │ │ └── jquery.colorpicker.gif │ ├── loading.gif │ ├── logo.png │ ├── open_off.png │ ├── open_on.png │ ├── plus.png │ ├── rails.png │ ├── remove_cards_off.png │ ├── remove_cards_on.png │ ├── rename.png │ ├── section_closed.png │ ├── section_opened.png │ ├── taskboard.png │ ├── taskboard_clone.png │ ├── taskboard_plus.png │ ├── tip-left.png │ ├── tip-top.png │ ├── tip.png │ └── warning.png ├── javascripts │ ├── footer.js │ ├── home.js │ ├── juggernaut │ │ ├── juggernaut.js │ │ └── swfobject.js │ ├── lib │ │ ├── excanvas.compiled.js │ │ ├── jqUnit.js │ │ ├── jquery-ui.min.js │ │ ├── jquery.colorpicker.js │ │ ├── jquery.cookie.js │ │ ├── jquery.flot.js │ │ ├── jquery.jeditable.js │ │ ├── jquery.js │ │ ├── jrails.js │ │ ├── juggernaut │ │ │ ├── jquerynaut.js │ │ │ ├── json.js │ │ │ ├── juggernaut.js │ │ │ └── swfobject.js │ │ └── showdown.js │ ├── taskboard.js │ └── utils.js ├── juggernaut │ ├── expressinstall.swf │ └── juggernaut.swf ├── robots.txt └── stylesheets │ ├── generic.css │ ├── home.css │ ├── login.css │ ├── print.css │ ├── taskboard.css │ └── testsuite.css ├── script ├── about ├── autospec ├── console ├── dbconsole ├── destroy ├── generate ├── performance │ ├── benchmarker │ ├── profiler │ └── request ├── plugin ├── process │ ├── inspector │ ├── reaper │ └── spawner ├── runner ├── server └── spin ├── spec ├── controllers │ ├── card_controller_spec.rb │ ├── juggernaut_sync_controller_spec.rb │ ├── login_controller_spec.rb │ ├── project_controller_spec.rb │ └── taskboard_controller_spec.rb ├── fixtures │ ├── cards.yml │ ├── columns.yml │ ├── hours.yml │ ├── jira-filter-01.xml │ ├── jira-issue-01.xml │ ├── projects.yml │ ├── rows.yml │ ├── taggings.yml │ ├── tags.yml │ ├── taskboards.yml │ └── users.yml ├── helpers │ ├── application_helper_spec.rb │ ├── card_helper_spec.rb │ ├── login_helper_spec.rb │ ├── project_helper_spec.rb │ └── taskboard_helper_spec.rb ├── javascripts │ ├── fixtures │ │ ├── home.html │ │ ├── screw.css │ │ └── utils.html │ ├── home_spec.js │ ├── spec_helper.js │ └── utils_spec.js ├── lib │ ├── jira_integration_spec.rb │ ├── jira_parser_spec.rb │ ├── taskboard_config_spec.rb │ ├── taskboard_version_spec.rb │ ├── url_parser_spec.rb │ └── utils_spec.rb ├── models │ ├── card_spec.rb │ ├── column_spec.rb │ ├── hour_spec.rb │ ├── project_spec.rb │ ├── row_spec.rb │ ├── taskboard_spec.rb │ └── user_spec.rb └── spec_helper.rb └── vendor └── plugins ├── acts_as_list ├── README ├── init.rb └── lib │ └── active_record │ └── acts │ └── list.rb ├── acts_as_taggable_on_steroids ├── CHANGELOG ├── MIT-LICENSE ├── README ├── Rakefile ├── generators │ └── acts_as_taggable_migration │ │ ├── acts_as_taggable_migration_generator.rb │ │ └── templates │ │ └── migration.rb ├── init.rb └── lib │ ├── acts_as_taggable.rb │ ├── tag.rb │ ├── tag_counts_extension.rb │ ├── tag_list.rb │ ├── tagging.rb │ └── tags_helper.rb ├── blue-ridge ├── LICENSE ├── LICENSE-Screw.Unit ├── LICENSE-Smoke ├── README.markdown ├── Rakefile ├── TODO.taskpaper ├── generators │ ├── blue_ridge │ │ ├── blue_ridge_generator.rb │ │ └── templates │ │ │ ├── application.html │ │ │ ├── application_spec.js │ │ │ ├── screw.css │ │ │ └── spec_helper.js │ └── javascript_spec │ │ ├── javascript_spec_generator.rb │ │ └── templates │ │ ├── fixture.html.erb │ │ └── javascript_spec.js.erb ├── lib │ ├── blue-ridge.js │ ├── blue_ridge.rb │ ├── consoleReportForRake.js │ ├── env.rhino.js │ ├── jquery-1.2.6.js │ ├── jquery-1.3.2.js │ ├── jquery.fn.js │ ├── jquery.print.js │ ├── js.jar │ ├── screw.behaviors.js │ ├── screw.builder.js │ ├── screw.events.js │ ├── screw.matchers.js │ ├── screw.mocking.js │ ├── screw.smok.js │ ├── shell.js │ ├── smok.js │ ├── smoke.core.js │ ├── smoke.mock.js │ ├── smoke.stub.js │ └── test_runner.js ├── spec │ ├── javascripts │ │ ├── fixtures │ │ │ ├── screw.behaviors.html │ │ │ ├── screw.matchers.html │ │ │ ├── screw.print.html │ │ │ ├── smoke.core.html │ │ │ ├── smoke.mock.html │ │ │ ├── smoke.screw_integration.html │ │ │ └── smoke.stub.html │ │ ├── screw.behaviors_spec.js │ │ ├── screw.matchers_spec.js │ │ ├── screw.print_spec.js │ │ ├── smoke.core_spec.js │ │ ├── smoke.mock_spec.js │ │ ├── smoke.screw_integration_spec.js │ │ ├── smoke.stub_spec.js │ │ └── spec_helper.js │ └── rubies │ │ ├── blue_ridge_spec.rb │ │ └── spec_helper.rb └── tasks │ └── javascript_testing_tasks.rake └── juggernaut_plugin ├── LICENSE ├── README ├── init.rb ├── install.rb ├── lib ├── juggernaut.rb └── juggernaut_helper.rb ├── media ├── expressinstall.swf ├── jquery.js ├── jquerynaut.js ├── json.js ├── juggernaut.as ├── juggernaut.js ├── juggernaut.swf ├── juggernaut.yml ├── juggernaut_hosts.yml ├── log │ └── juggernaut.log └── swfobject.js └── tasks └── juggernaut.rake /.gitignore: -------------------------------------------------------------------------------- 1 | Capfile 2 | 3 | # ignore config files but leave examples 4 | config/deploy.rb 5 | config/*.yml 6 | !config/*.example.yml 7 | 8 | coverage/ 9 | 10 | log/*.log 11 | log/*/*.log 12 | 13 | nbproject/ 14 | .idea/ 15 | .generators 16 | 17 | lib/tasks/cruise.rake 18 | lib/tasks/rspec.rake 19 | 20 | script/spec 21 | script/spec_server 22 | 23 | spec/rcov.opts 24 | spec/spec.opts 25 | 26 | test/ 27 | tmp/ 28 | taskboard_internal/ 29 | 30 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Taskboard 2 | ========= 3 | your on-line tool for task management fun 4 | 5 | http://taskboard.cognifide.com 6 | 7 | Copyright (c) 2008-2009 Cognifide 8 | http://www.cognifide.com 9 | 10 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require(File.join(File.dirname(__FILE__), 'config', 'boot')) 5 | 6 | require 'rake' 7 | require 'rake/testtask' 8 | require 'rake/rdoctask' 9 | 10 | require 'tasks/rails' 11 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class ApplicationController < ActionController::Base 19 | helper :all # include all helpers, all the time 20 | 21 | before_filter :authorize, :authorize_read_only 22 | 23 | # See ActionController::RequestForgeryProtection for details 24 | # Uncomment the :secret if you're not using the cookie session store 25 | protect_from_forgery # :secret => 'fba8a476189fb5d6dc6a7b9e889fb10f' 26 | 27 | # See ActionController::Base for details 28 | # Uncomment this to filter the contents of submitted sensitive data parameters 29 | # from your application log (in this case, all fields with names like "password"). 30 | # filter_parameter_logging :password 31 | 32 | def report_logger(id) 33 | @report_loggers = {} unless @report_loggers 34 | return @report_loggers[id] if @report_loggers[id] 35 | report_file_path = "#{RAILS_ROOT}/log/report/taskboard_#{id}.log" 36 | report_file = File.open(report_file_path, 'a') 37 | report_file.sync = true 38 | @report_loggers[id] = Logger.new(report_file) 39 | end 40 | 41 | private 42 | def authorize 43 | session[:original_uri] = request.request_uri unless request.xhr? 44 | if session[:user_id].nil? 45 | redirect_to(:controller => 'login', :action => 'login') 46 | end 47 | end 48 | 49 | def authorize_read_only 50 | session[:original_uri] = request.request_uri unless request.xhr? 51 | unless session[:user_id].nil? 52 | unless session[:editor] 53 | flash[:notice] = "You do not have permission to do that!" 54 | redirect_to(:controller => 'taskboard', :action => 'index') 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /app/controllers/login_controller.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class LoginController < ApplicationController 19 | before_filter [:authorize, :authorize_read_only], :except => ["login","logout"] 20 | 21 | def add_user 22 | @user = User.new(params[:user]) 23 | if request.post? and @user.save 24 | role = @user.editor? ? 'editor' : 'viewer' 25 | flash.now[:notice] = "Added new #{role} user #{@user.username}" 26 | @user = User.new 27 | end 28 | end 29 | 30 | def list_users 31 | @all_users = User.find(:all) 32 | end 33 | 34 | def login 35 | login = params[:login] 36 | password = params[:password] 37 | 38 | if request.post? 39 | if(login.blank? || password.blank?) 40 | flash.now[:notice] = "Please fill in both user name and password!" 41 | else 42 | clear_session 43 | user = User.authenticate(login, password) 44 | if user 45 | session[:user_id] = user.id 46 | session[:user] = user 47 | session[:editor] = user.editor? 48 | uri = session[:original_uri] 49 | session[:original_uri] = nil 50 | redirect_to(uri || {:controller => 'taskboard', :action => "index"}) 51 | else 52 | flash.now[:notice] = "Wrong user name or password!" 53 | end 54 | end 55 | end 56 | end 57 | 58 | def logout 59 | clear_session 60 | flash[:notice] = "You have logged out successfuly!"; 61 | redirect_to :controller => "login", :action => "login" 62 | end 63 | 64 | private 65 | 66 | def clear_session 67 | session[:user_id] = nil 68 | session[:user] = nil 69 | session[:editor] = false 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /app/controllers/project_controller.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class ProjectController < ApplicationController 19 | 20 | before_filter :authorize_read_only, :except => ["index"] 21 | 22 | def index 23 | @projects = Project.find(:all, :order => "name") 24 | end 25 | 26 | def add 27 | project = Project.new 28 | project.name = params[:name].blank? ? Project::DEFAULT_NAME : params[:name] 29 | project.save! 30 | redirect_to :action => 'index' 31 | end 32 | 33 | def rename 34 | project = Project.find(params[:id].to_i) 35 | if not params[:name].blank? 36 | project.name = params[:name] 37 | project.save! 38 | render :json => { :status => 'success', :message => project.name } 39 | else 40 | render :json => { :status => 'error', :message => "Project's name cannot be empty" } 41 | end 42 | end 43 | 44 | end 45 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | # Methods added to this helper will be available to all templates in the application. 19 | module ApplicationHelper 20 | 21 | # just wrap and produce js like data structure 22 | def burndown burndown_aware 23 | data = burndown_aware.burndown.sort.to_a.map{ |x| 24 | # split string so we can get seconds from the epoch (as flot wants us to do) 25 | [ make_time( x[0] ) * 1000, x[1] ] 26 | } 27 | data.inspect 28 | end 29 | 30 | def make_time(time_in_string) 31 | time = time_in_string.split("-") 32 | Time.mktime(time[0], time[1], time[2], 0, 0, 0, 0).to_i 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /app/helpers/card_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | module CardHelper 19 | end 20 | -------------------------------------------------------------------------------- /app/helpers/juggernaut_sync_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | module JuggernautSyncHelper 19 | end 20 | -------------------------------------------------------------------------------- /app/helpers/login_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | module LoginHelper 19 | end 20 | -------------------------------------------------------------------------------- /app/helpers/project_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | module ProjectHelper 19 | end 20 | -------------------------------------------------------------------------------- /app/helpers/taskboard_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | module TaskboardHelper 19 | end 20 | -------------------------------------------------------------------------------- /app/models/column.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class Column < ActiveRecord::Base 19 | belongs_to :taskboard 20 | 21 | has_many :cards do 22 | def in_row(row) 23 | find(:all, :conditions => ["row_id = ?", row.id], :order => "position") 24 | end 25 | end 26 | 27 | acts_as_list :scope => :taskboard 28 | 29 | DEFAULT_NAME = 'Brave new column' 30 | 31 | def clone taskboard_id = taskboard_id 32 | Column.new(:name => name, :position => position, :taskboard_id => taskboard_id) 33 | end 34 | 35 | def to_json options = {} 36 | options[:include] = { :cards => { :methods => [:tag_list, :hours_left, :hours_left_updated] }} 37 | options[:except] = [:created_at, :updated_at, :taskboard_id] 38 | super(options) 39 | end 40 | 41 | end 42 | -------------------------------------------------------------------------------- /app/models/hour.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class Hour < ActiveRecord::Base 19 | belongs_to :card 20 | end 21 | -------------------------------------------------------------------------------- /app/models/project.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class Project < ActiveRecord::Base 19 | 20 | validates_presence_of :name 21 | 22 | has_many :taskboards 23 | 24 | DEFAULT_NAME = "Brand new project" 25 | 26 | end 27 | -------------------------------------------------------------------------------- /app/models/row.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class Row < ActiveRecord::Base 19 | belongs_to :taskboard 20 | 21 | has_many :cards do 22 | def in_column(column) 23 | find(:all, :conditions => ["column_id = ?", column.id], :order => "position") 24 | end 25 | end 26 | 27 | acts_as_list :scope => :taskboard 28 | 29 | DEFAULT_NAME = 'Brave new row' 30 | 31 | def clone taskboard_id = taskboard_id 32 | Row.new(:name => name, :position => position, :taskboard_id => taskboard_id) 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /app/models/taskboard.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class Taskboard < ActiveRecord::Base 19 | 20 | validates_presence_of :name 21 | 22 | belongs_to :project 23 | 24 | has_many :cards 25 | has_many :columns, :order => "position" 26 | has_many :rows, :order => "position" 27 | 28 | DEFAULT_NAME = "Brand new taskboard" 29 | 30 | def clone 31 | clonned_taskboard = Taskboard.new(:name => name, :project => project) 32 | 33 | columns_map = {} 34 | rows_map = {} 35 | 36 | columns.sort{|col1, col2| col1.position <=> col2.position}.each { |column| 37 | clonned_column = column.clone 38 | clonned_taskboard.columns << clonned_column 39 | columns_map[column.id] = clonned_column 40 | } 41 | 42 | rows.sort{|row1, row2| row1.position <=> row2.position}.each { |row| 43 | clonned_row = row.clone 44 | clonned_taskboard.rows << clonned_row 45 | rows_map[row.id] = clonned_row 46 | } 47 | 48 | clonned_taskboard.save! 49 | 50 | cards.sort{|c1, c2| c1.position <=> c2.position}.each { |card| 51 | clonned_card = card.clone clonned_taskboard.id, columns_map[card.column_id].id, rows_map[card.row_id].id 52 | clonned_card.save! 53 | } 54 | 55 | clonned_taskboard 56 | end 57 | 58 | def burndown 59 | burndown = Hash.new(0) 60 | self.cards.each { |card| 61 | card.burndown.each_pair { |date, hours| 62 | burndown[date] += hours 63 | } 64 | } 65 | 66 | return burndown 67 | end 68 | 69 | def to_json options = {} 70 | options[:include] = { :columns => {}, :rows => {}, :cards => { :methods => [:tag_list, :hours_left, :hours_left_updated] } } 71 | options[:except] = [:created_at, :updated_at] 72 | super(options) 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class User < ActiveRecord::Base 19 | validates_presence_of :username 20 | validates_uniqueness_of :username 21 | 22 | attr_accessor :password_confirmation 23 | validates_confirmation_of :password 24 | 25 | def validate 26 | errors.add_to_base("No password") if hashed_password.blank? 27 | end 28 | 29 | def password=(pwd) 30 | @password = pwd 31 | create_new_salt 32 | self.hashed_password = User.encrypted_password(self.password, self.salt) 33 | end 34 | 35 | def password 36 | @password 37 | end 38 | 39 | def self.authenticate(username, password) 40 | user = self.find_by_username(username) 41 | if user 42 | expected_password = encrypted_password(password, user.salt) 43 | user = nil if user.hashed_password != expected_password 44 | end 45 | user 46 | end 47 | 48 | private 49 | 50 | def create_new_salt 51 | self.salt = self.object_id.to_s + rand.to_s 52 | end 53 | 54 | def self.encrypted_password(password, salt) 55 | string_to_hash = password + "taskboard".reverse + salt 56 | Digest::SHA1.hexdigest(string_to_hash) 57 | end 58 | 59 | end 60 | -------------------------------------------------------------------------------- /app/views/login/_user_meta.html.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright (C) 2009 Cognifide 3 | 4 | This file is part of Taskboard. 5 | 6 | Taskboard is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Taskboard is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Taskboard. If not, see . 18 | -%> 19 | <%= session[:user].username %> - <%= link_to "Logout", { :controller => "login", :action => "logout" }, :title => "Logout from Taskboard app" %> 20 | -------------------------------------------------------------------------------- /app/views/login/add_user.html.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright (C) 2009 Cognifide 3 | 4 | This file is part of Taskboard. 5 | 6 | Taskboard is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Taskboard is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Taskboard. If not, see . 18 | -%> 19 | 21 | 22 | 23 | 24 | Taskboard: login page 25 | <%= stylesheet_link_tag 'login' %> 26 | 27 | 28 |

Taskboard

29 | <%= link_to "List users", :controller => 'login', :action => 'list_users' %> 30 | <% if flash[:notice] -%> 31 |
<%= flash[:notice] %>
32 | <% end -%> 33 | <%= error_messages_for 'user' %> 34 | <% form_for :user do |form| %> 35 |
36 |
37 |
38 |
<%= form.text_field :username, :size => 40 %>
39 |
40 |
<%= form.password_field :password, :size => 40 %>
41 |
42 |
<%= form.password_field :password_confirmation, :size => 40 %>
43 |
44 |
<%= form.check_box :editor %>
45 |
46 | <%= submit_tag "Add user" %> 47 |
48 | <% end %> 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/views/login/list_users.html.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright (C) 2009 Cognifide 3 | 4 | This file is part of Taskboard. 5 | 6 | Taskboard is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Taskboard is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Taskboard. If not, see . 18 | -%> 19 | 21 | 22 | 23 | 24 | Taskboard: login page 25 | <%= stylesheet_link_tag 'login' %> 26 | 27 | 28 |

Taskboard

29 | <%= link_to "Add user", :controller => 'login', :action => 'add_user' %> 30 |
    31 | <% for user in @all_users -%> 32 |
  • <%= h(user.username) %><% if user.editor %> - editor<% end %>
  • 33 | <% end -%> 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /app/views/login/login.html.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright (C) 2009 Cognifide 3 | 4 | This file is part of Taskboard. 5 | 6 | Taskboard is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Taskboard is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Taskboard. If not, see . 18 | -%> 19 | 21 | 22 | 23 | 24 | Taskboard: login page 25 | <%= stylesheet_link_tag 'login' %> 26 | <%= javascript_include_tag 'lib/jquery', 'lib/jquery-ui.min', 'utils', 'footer' %> 27 | 28 | 29 |

Taskboard

30 |
31 | <% if flash[:notice] -%> 32 |
<%= flash[:notice] %>
33 | <% end -%> 34 | <% form_tag do %> 35 |
36 |
37 |
38 |
<%= text_field_tag :login, params[:login] %>
39 |
40 |
<%= password_field_tag :password, params[:password] %>
41 |
42 | <%= submit_tag "Login" %> 43 |
44 | <% end %> 45 |
46 | <%= render :partial => 'project/footer' %> 47 | 48 | 49 | -------------------------------------------------------------------------------- /app/views/project/_footer.html.erb: -------------------------------------------------------------------------------- 1 | 13 | 14 | -------------------------------------------------------------------------------- /app/views/project/_project.html.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright (C) 2009 Cognifide 3 | 4 | This file is part of Taskboard. 5 | 6 | Taskboard is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Taskboard is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Taskboard. If not, see . 18 | -%> 19 |
20 | <%= truncate(h(project.name), :length => 25) %> (<%= project.taskboards.size %>) 21 | <% if session[:editor] -%> 22 | 30 | <% end -%> 31 |
32 |
33 |
    34 | <% if project.taskboards.size > 0 -%> 35 | 36 | <%= render :partial => 'taskboard/taskboard', :collection => project.taskboards.sort_by{|t| t.name.downcase} %> 37 | <% else -%> 38 |
  • There are no taskboards in this project yet.
  • 39 | <% end %> 40 | <% if session[:editor] -%> 41 |
  • 42 |
    43 |
    44 | 45 | 46 |
    47 | 48 | 49 |
    50 |
    51 |
    52 |
  • 53 | <% end -%> 54 |
55 |
56 | -------------------------------------------------------------------------------- /app/views/project/index.html.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright (C) 2009 Cognifide 3 | 4 | This file is part of Taskboard. 5 | 6 | Taskboard is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Taskboard is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Taskboard. If not, see . 18 | -%> 19 | 21 | 22 | 23 | Taskboards 24 | <%= stylesheet_link_tag 'home' %> 25 | <%= javascript_include_tag 'lib/jquery', 'lib/jquery-ui.min', 'utils', 'home', 'lib/jquery.jeditable', 'footer' %> 26 | 31 | 32 | 33 | 34 | 35 |
36 | Hello <%= render :partial => "login/user_meta" %> 37 |
38 | 39 |

Taskboard

40 |
41 | <% if session[:editor] -%> 42 |
43 |
44 |
45 | 46 |
47 | 48 | 49 |
50 |
51 |
52 |
53 | <% end -%> 54 |
55 | 59 |
60 | <%= render :partial => 'project', :collection => @projects %> 61 |
62 | <%= render :partial => 'footer' %> 63 | 64 | 65 | -------------------------------------------------------------------------------- /app/views/taskboard/_taskboard.html.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright (C) 2009 Cognifide 3 | 4 | This file is part of Taskboard. 5 | 6 | Taskboard is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | Taskboard is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with Taskboard. If not, see . 18 | -%> 19 |
  • 20 | <%= link_to truncate(h(taskboard.name), :length => 35), { :controller => 'taskboard', :action => 'show', :id => taskboard }, :title => "Open '#{h(taskboard.name)}' taskboard" %> 21 | <% if session[:editor] -%> 22 |
      23 |
    • 24 |
    • 25 | <% link_to({ :controller => 'taskboard', :action => 'clone_taskboard', :id => taskboard }, :title => "Create a copy of '#{h(taskboard.name)}'", :rel => 'clone', :class => 'cloneTaskboard') do -%> 26 | Create a copy of '<%= h(taskboard.name) %>' 27 | <% end -%> 28 |
    • 29 |
    30 | <% end -%> 31 |
  • 32 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # Don't change this file! 2 | # Configure your app in config/environment.rb and config/environments/*.rb 3 | 4 | RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT) 5 | 6 | module Rails 7 | class << self 8 | def boot! 9 | unless booted? 10 | preinitialize 11 | pick_boot.run 12 | end 13 | end 14 | 15 | def booted? 16 | defined? Rails::Initializer 17 | end 18 | 19 | def pick_boot 20 | (vendor_rails? ? VendorBoot : GemBoot).new 21 | end 22 | 23 | def vendor_rails? 24 | File.exist?("#{RAILS_ROOT}/vendor/rails") 25 | end 26 | 27 | def preinitialize 28 | load(preinitializer_path) if File.exist?(preinitializer_path) 29 | end 30 | 31 | def preinitializer_path 32 | "#{RAILS_ROOT}/config/preinitializer.rb" 33 | end 34 | end 35 | 36 | class Boot 37 | def run 38 | load_initializer 39 | Rails::Initializer.run(:set_load_path) 40 | end 41 | end 42 | 43 | class VendorBoot < Boot 44 | def load_initializer 45 | require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer" 46 | Rails::Initializer.run(:install_gem_spec_stubs) 47 | Rails::GemDependency.add_frozen_gem_path 48 | end 49 | end 50 | 51 | class GemBoot < Boot 52 | def load_initializer 53 | self.class.load_rubygems 54 | load_rails_gem 55 | require 'initializer' 56 | end 57 | 58 | def load_rails_gem 59 | if version = self.class.gem_version 60 | gem 'rails', version 61 | else 62 | gem 'rails' 63 | end 64 | rescue Gem::LoadError => load_error 65 | $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.) 66 | exit 1 67 | end 68 | 69 | class << self 70 | def rubygems_version 71 | Gem::RubyGemsVersion rescue nil 72 | end 73 | 74 | def gem_version 75 | if defined? RAILS_GEM_VERSION 76 | RAILS_GEM_VERSION 77 | elsif ENV.include?('RAILS_GEM_VERSION') 78 | ENV['RAILS_GEM_VERSION'] 79 | else 80 | parse_gem_version(read_environment_rb) 81 | end 82 | end 83 | 84 | def load_rubygems 85 | min_version = '1.3.2' 86 | require 'rubygems' 87 | unless rubygems_version >= min_version 88 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.) 89 | exit 1 90 | end 91 | 92 | rescue LoadError 93 | $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org) 94 | exit 1 95 | end 96 | 97 | def parse_gem_version(text) 98 | $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/ 99 | end 100 | 101 | private 102 | def read_environment_rb 103 | File.read("#{RAILS_ROOT}/config/environment.rb") 104 | end 105 | end 106 | end 107 | end 108 | 109 | # All that for this: 110 | Rails.boot! 111 | -------------------------------------------------------------------------------- /config/database.example.yml: -------------------------------------------------------------------------------- 1 | development: 2 | host: localhost 3 | adapter: mysql 4 | database: taskboard_development 5 | port: 3306 6 | username: root 7 | password: 8 | encoding: utf8 9 | 10 | # Warning: The database defined as 'test' will be erased and 11 | # re-generated from your development database when you run 'rake'. 12 | # Do not set this db to the same as development or production. 13 | test: 14 | host: localhost 15 | adapter: mysql 16 | database: taskboard_test 17 | port: 3306 18 | username: root 19 | password: 20 | encoding: utf8 21 | 22 | production: 23 | host: localhost 24 | adapter: mysql 25 | database: taskboard_production 26 | port: 3306 27 | username: root 28 | password: 29 | encoding: utf8 30 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file 2 | 3 | # Uncomment below to force Rails into production mode when 4 | # you don't control web/app server and can't set it the proper way 5 | # ENV['RAILS_ENV'] ||= 'production' 6 | 7 | # Specifies gem version of Rails to use when vendor/rails is not present 8 | RAILS_GEM_VERSION = '2.3.5' unless defined? RAILS_GEM_VERSION 9 | 10 | # Bootstrap the Rails environment, frameworks, and default configuration 11 | require File.join(File.dirname(__FILE__), 'boot') 12 | 13 | Rails::Initializer.run do |config| 14 | # Settings in config/environments/* take precedence over those specified here. 15 | # Application configuration should go into files in config/initializers 16 | # -- all .rb files in that directory are automatically loaded. 17 | # See Rails::Configuration for more options. 18 | 19 | # Skip frameworks you're not going to use. To use Rails without a database 20 | # you must remove the Active Record framework. 21 | # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] 22 | 23 | # Specify gems that this application depends on. 24 | # They can then be installed with "rake gems:install" on new installations. 25 | # config.gem "bj" 26 | # config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net" 27 | # config.gem "aws-s3", :lib => "aws/s3" 28 | 29 | config.gem "juggernaut" 30 | 31 | # Only load the plugins named here, in the order given. By default, all plugins 32 | # in vendor/plugins are loaded in alphabetical order. 33 | # :all can be used as a placeholder for all plugins not explicitly named 34 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ] 35 | 36 | # Add additional load paths for your own custom dirs 37 | # config.load_paths += %W( #{RAILS_ROOT}/extras ) 38 | 39 | # Force all environments to use the same logger level 40 | # (by default production uses :info, the others :debug) 41 | # config.log_level = :debug 42 | 43 | # Make Time.zone default to the specified zone, and make Active Record store time values 44 | # in the database in UTC, and return them converted to the specified local zone. 45 | # Run "rake -D time" for a list of tasks for finding time zone names. Comment line to use default local time. 46 | config.time_zone = 'UTC' 47 | 48 | # Your secret key for verifying cookie session data integrity. 49 | # If you change this key, all old sessions will become invalid! 50 | # Make sure the secret is at least 30 characters and all random, 51 | # no regular words or you'll be exposed to dictionary attacks. 52 | config.action_controller.session = { 53 | :session_key => '_taskboard_session', 54 | :secret => '3e5780da30892c424c7fb051c8cd8bc97cdb312c00b0cfb8a476c8958d1fdbcd201859f92eb2716487d0ab1665e0a56f002de854d38cc121e849480bb49d95c8' 55 | } 56 | 57 | # Use the database for sessions instead of the cookie-based default, 58 | # which shouldn't be used to store highly confidential information 59 | # (create the session table with "rake db:sessions:create") 60 | config.action_controller.session_store = :active_record_store 61 | 62 | # Use SQL instead of Active Record's schema dumper when creating the test database. 63 | # This is necessary if your schema can't be completely dumped by the schema dumper, 64 | # like if you have constraints or database-specific column types 65 | # config.active_record.schema_format = :sql 66 | 67 | # Activate observers that should always be running 68 | # config.active_record.observers = :cacher, :garbage_collector 69 | 70 | 71 | 72 | end 73 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | # Settings specified here will take precedence over those in config/environment.rb 2 | 3 | # In the development environment your application's code is reloaded on 4 | # every request. This slows down response time but is perfect for development 5 | # since you don't have to restart the webserver when you make code changes. 6 | config.cache_classes = false 7 | 8 | # Log error messages when you accidentally call methods on nil. 9 | config.whiny_nils = true 10 | 11 | # Show full error reports and disable caching 12 | config.action_controller.consider_all_requests_local = true 13 | config.action_view.debug_rjs = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send 17 | config.action_mailer.raise_delivery_errors = false 18 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | # Settings specified here will take precedence over those in config/environment.rb 2 | 3 | # The production environment is meant for finished, "live" apps. 4 | # Code is not reloaded between requests 5 | config.cache_classes = true 6 | 7 | # Use a different logger for distributed setups 8 | # config.logger = SyslogLogger.new 9 | 10 | # Full error reports are disabled and caching is turned on 11 | config.action_controller.consider_all_requests_local = false 12 | config.action_controller.perform_caching = true 13 | config.action_view.cache_template_loading = true 14 | 15 | # Use a different cache store in production 16 | # config.cache_store = :mem_cache_store 17 | 18 | # Enable serving of images, stylesheets, and javascripts from an asset server 19 | # config.action_controller.asset_host = "http://assets.example.com" 20 | 21 | # Disable delivery errors, bad email addresses will be ignored 22 | # config.action_mailer.raise_delivery_errors = false 23 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | # Settings specified here will take precedence over those in config/environment.rb 2 | 3 | # The test environment is used exclusively to run your application's 4 | # test suite. You never need to work with it otherwise. Remember that 5 | # your test database is "scratch space" for the test suite and is wiped 6 | # and recreated between test runs. Don't rely on the data there! 7 | config.cache_classes = true 8 | 9 | # Log error messages when you accidentally call methods on nil. 10 | config.whiny_nils = true 11 | 12 | # Show full error reports and disable caching 13 | config.action_controller.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Disable request forgery protection in test environment 17 | config.action_controller.allow_forgery_protection = false 18 | 19 | # Tell Action Mailer not to deliver emails to the real world. 20 | # The :test delivery method accumulates sent emails in the 21 | # ActionMailer::Base.deliveries array. 22 | config.action_mailer.delivery_method = :test 23 | 24 | config.gem 'rspec', :lib => 'spec' 25 | config.gem 'rspec-rails', :lib => 'spec' 26 | config.gem 'ZenTest', :lib => false 27 | config.gem 'rcov', :lib => false 28 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format 4 | # (all these examples are active by default): 5 | # ActiveSupport::Inflector.inflections do |inflect| 6 | # inflect.plural /^(ox)$/i, '\1en' 7 | # inflect.singular /^(ox)en/i, '\1' 8 | # inflect.irregular 'person', 'people' 9 | # inflect.uncountable %w( fish sheep ) 10 | # end 11 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | # Mime::Type.register_alias "text/html", :iphone 6 | -------------------------------------------------------------------------------- /config/initializers/new_rails_defaults.rb: -------------------------------------------------------------------------------- 1 | # These settings change the behavior of Rails 2 apps and will be defaults 2 | # for Rails 3. You can remove this initializer when Rails 3 is released. 3 | 4 | if defined?(ActiveRecord) 5 | # Include Active Record class name as root for JSON serialized output. 6 | ActiveRecord::Base.include_root_in_json = true 7 | 8 | # Store the full class name (including module namespace) in STI type column. 9 | ActiveRecord::Base.store_full_sti_class = true 10 | end 11 | 12 | # Use ISO 8601 format for JSON serialized times and dates. 13 | ActiveSupport.use_standard_json_time_format = true 14 | 15 | # Don't escape HTML entities in JSON, leave that for the #json_escape helper. 16 | # if you're including raw json in an HTML page. 17 | ActiveSupport.escape_html_entities_in_json = false -------------------------------------------------------------------------------- /config/initializers/require.rb: -------------------------------------------------------------------------------- 1 | # include Taskboard version file 2 | require 'taskboard_version' 3 | -------------------------------------------------------------------------------- /config/juggernaut_hosts.example.yml: -------------------------------------------------------------------------------- 1 | # You should list any juggernaut hosts here. 2 | # You need only specify the secret key if you're using that type of authentication (see juggernaut.yml) 3 | # 4 | # Name: Mapping: 5 | # :port internal push server's port 6 | # :host internal push server's host/ip 7 | # :public_host public push server's host/ip (accessible from external clients) 8 | # :public_port public push server's port 9 | # :secret_key (optional) shared secret (should map to the key specified in the push server's config) 10 | # :environment (optional) limit host to a particular RAILS_ENV 11 | 12 | :hosts: 13 | - :port: 5001 14 | :host: 127.0.0.1 15 | :public_host: 127.0.0.1 # change this to your public IP/host to make juggernaut accessible externally 16 | :public_port: 5001 # make sure this is the same as public port in juggernaut.yml config 17 | # :secret_key: your_secret_key 18 | # :environment: :development 19 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | ActionController::Routing::Routes.draw do |map| 2 | # The priority is based upon order of creation: first created -> highest priority. 3 | 4 | # Sample of regular route: 5 | # map.connect 'products/:id', :controller => 'catalog', :action => 'view' 6 | # Keep in mind you can assign values other than :controller and :action 7 | 8 | # Sample of named route: 9 | # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase' 10 | # This route can be invoked with purchase_url(:id => product.id) 11 | map.home 'home', :controller => 'project', :action => 'index' 12 | 13 | # Sample resource route (maps HTTP verbs to controller actions automatically): 14 | # map.resources :products 15 | 16 | # Sample resource route with options: 17 | # map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get } 18 | 19 | # Sample resource route with sub-resources: 20 | # map.resources :products, :has_many => [ :comments, :sales ], :has_one => :seller 21 | 22 | # Sample resource route with more complex sub-resources 23 | # map.resources :products do |products| 24 | # products.resources :comments 25 | # products.resources :sales, :collection => { :recent => :get } 26 | # end 27 | 28 | # Sample resource route within a namespace: 29 | # map.namespace :admin do |admin| 30 | # # Directs /admin/products/* to Admin::ProductsController (app/controllers/admin/products_controller.rb) 31 | # admin.resources :products 32 | # end 33 | 34 | # You can have the root of your site routed with map.root -- just remember to delete public/index.html. 35 | map.root :controller => "project" 36 | 37 | # See how all your routes lay out with "rake routes" 38 | 39 | # Install the default routes as the lowest priority. 40 | # Note: These default routes make all actions in every controller accessible via GET requests. You should 41 | # consider removing the them or commenting them out if you're using named routes and resources. 42 | map.connect ':controller/:action/:id' 43 | map.connect ':controller/:action/:id.:format' 44 | end 45 | -------------------------------------------------------------------------------- /config/taskboard.example.yml: -------------------------------------------------------------------------------- 1 | --- !ruby/object:TaskboardConfig 2 | jira_auth_data: 3 | jira.example.com: 4 | os_username: your_jira_username 5 | os_password: your_jira_password 6 | jira.other.example.com: 7 | os_username: your_other_jira_username 8 | os_password: your_other_jira_password 9 | 10 | -------------------------------------------------------------------------------- /db/migrate/20081010142942_create_cards.rb: -------------------------------------------------------------------------------- 1 | class CreateCards < ActiveRecord::Migration 2 | def self.up 3 | create_table :cards do |t| 4 | t.text :name, :null => false 5 | t.text :notes, :null => true 6 | t.integer :taskboard_id 7 | t.integer :column_id 8 | t.integer :position, :null => true 9 | t.string :issue_no, :null => true, :limit => 128 10 | t.string :color, :null => true, :limit => 128 11 | t.string :url, :null => true 12 | t.timestamps 13 | end 14 | end 15 | 16 | def self.down 17 | drop_table :cards 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /db/migrate/20081013145250_create_taskboards.rb: -------------------------------------------------------------------------------- 1 | class CreateTaskboards < ActiveRecord::Migration 2 | def self.up 3 | create_table :taskboards do |t| 4 | t.text :name, :null => false 5 | t.timestamps 6 | end 7 | end 8 | 9 | def self.down 10 | drop_table :taskboards 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20081013170754_create_columns.rb: -------------------------------------------------------------------------------- 1 | class CreateColumns < ActiveRecord::Migration 2 | def self.up 3 | create_table :columns do |t| 4 | t.text :name, :null => false 5 | t.integer :position, :null => true 6 | t.integer :taskboard_id, :null => false 7 | t.timestamps 8 | end 9 | end 10 | 11 | def self.down 12 | drop_table :columns 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20081031114623_foreign_keys.rb: -------------------------------------------------------------------------------- 1 | require "migration_helpers" 2 | 3 | class ForeignKeys < ActiveRecord::Migration 4 | extend MigrationHelpers 5 | 6 | def self.up 7 | add_foreign_key(:cards, :taskboard_id, :taskboards) 8 | add_foreign_key(:cards, :column_id, :columns) 9 | add_foreign_key(:columns, :taskboard_id, :taskboards) 10 | end 11 | 12 | def self.down 13 | remove_foreign_key(:cards, :taskboard_id) 14 | remove_foreign_key(:cards, :column_id) 15 | remove_foreign_key(:columns, :taskboard_id) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/migrate/20081127152023_acts_as_taggable_migration.rb: -------------------------------------------------------------------------------- 1 | class ActsAsTaggableMigration < ActiveRecord::Migration 2 | def self.up 3 | create_table :tags do |t| 4 | t.column :name, :string 5 | end 6 | 7 | create_table :taggings do |t| 8 | t.column :tag_id, :integer 9 | t.column :taggable_id, :integer 10 | 11 | # You should make sure that the column created is 12 | # long enough to store the required class names. 13 | t.column :taggable_type, :string 14 | 15 | t.column :created_at, :datetime 16 | end 17 | 18 | add_index :taggings, :tag_id 19 | add_index :taggings, [:taggable_id, :taggable_type] 20 | end 21 | 22 | def self.down 23 | drop_table :taggings 24 | drop_table :tags 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /db/migrate/20081205134317_create_hours.rb: -------------------------------------------------------------------------------- 1 | class CreateHours < ActiveRecord::Migration 2 | def self.up 3 | create_table :hours do |t| 4 | t.datetime :date, :null => false 5 | t.integer :left, :null => false 6 | t.integer :card_id 7 | t.timestamps 8 | end 9 | end 10 | 11 | def self.down 12 | drop_table :hours 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20090317140555_create_sessions.rb: -------------------------------------------------------------------------------- 1 | class CreateSessions < ActiveRecord::Migration 2 | def self.up 3 | create_table :sessions do |t| 4 | t.string :session_id, :null => false 5 | t.text :data 6 | t.timestamps 7 | end 8 | 9 | add_index :sessions, :session_id 10 | add_index :sessions, :updated_at 11 | end 12 | 13 | def self.down 14 | drop_table :sessions 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20090428084605_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration 2 | def self.up 3 | create_table :users do |t| 4 | t.string :username, :null => false 5 | t.string :hashed_password, :null => false 6 | t.string :salt, :null => false 7 | t.boolean :editor 8 | t.string :email 9 | t.timestamps 10 | end 11 | end 12 | 13 | def self.down 14 | drop_table :users 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20090428123003_add_default_users.rb: -------------------------------------------------------------------------------- 1 | class AddDefaultUsers < ActiveRecord::Migration 2 | def self.up 3 | User.create!(:username => "taskboard", :password => "taskboard", :editor => true) 4 | end 5 | 6 | def self.down 7 | User.delete_all 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20090706124829_create_rows.rb: -------------------------------------------------------------------------------- 1 | require "migration_helpers" 2 | 3 | class CreateRows < ActiveRecord::Migration 4 | extend MigrationHelpers 5 | 6 | def self.up 7 | create_table :rows do |t| 8 | t.text :name, :null => false 9 | t.integer :position, :null => true 10 | t.integer :taskboard_id, :null => false 11 | t.timestamps 12 | end 13 | 14 | add_foreign_key(:rows, :taskboard_id, :taskboards) 15 | end 16 | 17 | def self.down 18 | remove_foreign_key(:rows, :taskboard_id) 19 | 20 | drop_table :rows 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /db/migrate/20090707130233_add_cards_to_rows.rb: -------------------------------------------------------------------------------- 1 | require "migration_helpers" 2 | 3 | class AddCardsToRows < ActiveRecord::Migration 4 | extend MigrationHelpers 5 | 6 | def self.up 7 | add_column :cards, :row_id, :integer 8 | add_foreign_key(:cards, :row_id, :rows) 9 | 10 | say_with_time 'Creating default rows for all existing taskboards' do 11 | Taskboard.find(:all).each do |taskboard| 12 | row = Row.create!(:name => "Default row", :taskboard_id => taskboard.id) 13 | taskboard.cards.each do |card| 14 | card.row_id = row.id; 15 | card.save! 16 | end 17 | end 18 | end 19 | end 20 | 21 | def self.down 22 | remove_foreign_key(:cards, :row_id) 23 | remove_column :cards, :row_id 24 | 25 | Row.delete_all 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /db/migrate/20090922095631_create_projects.rb: -------------------------------------------------------------------------------- 1 | class CreateProjects < ActiveRecord::Migration 2 | def self.up 3 | create_table :projects do |t| 4 | t.text :name, :null => false 5 | t.timestamps 6 | end 7 | end 8 | 9 | def self.down 10 | drop_table :projects 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20090922100811_add_taskboards_to_projects.rb: -------------------------------------------------------------------------------- 1 | require "migration_helpers" 2 | 3 | class AddTaskboardsToProjects < ActiveRecord::Migration 4 | extend MigrationHelpers 5 | 6 | def self.up 7 | add_column :taskboards, :project_id, :integer 8 | add_foreign_key(:taskboards, :project_id, :projects) 9 | 10 | project = Project.create!(:name => "All taskboards") 11 | say_with_time 'Creating default project for all existing taskboards' do 12 | Taskboard.find(:all).each do |taskboard| 13 | taskboard.project = project 14 | taskboard.save! 15 | end 16 | end 17 | end 18 | 19 | def self.down 20 | remove_foreign_key(:taskboards, :project_id) 21 | remove_column :taskboards, :project_id 22 | 23 | Project.delete_all 24 | end 25 | end 26 | 27 | -------------------------------------------------------------------------------- /lib/jira_integration.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require 'net/http' 19 | require 'net/https' 20 | require 'uri' 21 | require 'taskboard_config' 22 | 23 | class JiraIntegration 24 | 25 | def self.get url 26 | uri = get_uri_to_xml(url) 27 | 28 | http = Net::HTTP.new(uri.host, uri.port) 29 | http.use_ssl = true if uri.port == Net::HTTP.https_default_port 30 | 31 | # append credentials 32 | credentials = self.auth_data[uri.host].to_a.collect{ |a| a.join('=') }.join('&') 33 | uri.query = uri.query.nil? ? credentials : uri.query + '&' + credentials 34 | 35 | http.get(uri.path + '?' + uri.query).body 36 | end 37 | 38 | def self.get_uri_to_xml url 39 | uri = URI.parse(url) 40 | 41 | # leave all request to xml file untouched 42 | unless uri.path.ends_with?('.xml') 43 | 44 | # check if it is request for single issue or bunch of them (IssueNavigator) 45 | if uri.path =~ /secure\/IssueNavigator.jspa/ 46 | 47 | # distinguish between search results and filters 48 | if uri.query =~ /requestId=[\d]*$/ 49 | 50 | # parse filter id 51 | filter_id = uri.query[/requestId=[\d]*$/][/\d+/] 52 | uri.path.sub!('secure/IssueNavigator.jspa', 53 | 'sr/jira.issueviews:searchrequest-xml/' + filter_id + '/SearchRequest-' + filter_id + '.xml') 54 | else 55 | 56 | # just modify path 57 | uri.path.sub!('secure/IssueNavigator.jspa', 58 | 'sr/jira.issueviews:searchrequest-xml/temp/SearchRequest.xml') 59 | end 60 | 61 | # remove 'mode' and 'requestId' parameters and add 'tempMax' 62 | uri.query.gsub!(/&?(mode=\w+|requestId=\w+|reset=\w+)/, '') 63 | uri.query += '&' unless uri.query.empty? 64 | uri.query += 'tempMax=1000' 65 | 66 | else 67 | # single issue 68 | issue_id = uri.path[/[\w-]*$/] 69 | uri.path = uri.path.sub('browse', 'si/jira.issueviews:issue-xml') + '/' + issue_id + '.xml' 70 | end 71 | end 72 | uri 73 | end 74 | 75 | def self.is_valid_url? url 76 | not self.auth_data.nil? and self.auth_data.keys.any? { |base| url.include? base } 77 | end 78 | 79 | private 80 | 81 | def self.auth_data 82 | TaskboardConfig.instance.jira_auth_data 83 | end 84 | end 85 | 86 | -------------------------------------------------------------------------------- /lib/jira_parser.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require 'rexml/document' 19 | 20 | include REXML 21 | 22 | class JiraParser 23 | 24 | attr_accessor :xml, :issues 25 | 26 | # TODO use SAX and optimize this method (http://www.rubyxml.com/articles/REXML/Stream_Parsing_with_REXML) 27 | def do_parse! 28 | doc = Document.new(xml) 29 | @issues = Array.new 30 | doc.root.each_element('channel/item') do |item| 31 | card = Card.new 32 | card.name = item.elements['summary'].text 33 | card.issue_no = item.elements['key'].text 34 | if (card.issue_no) 35 | card.url = item.elements['link'].text 36 | end 37 | @issues << card 38 | end 39 | end 40 | 41 | def self.is_jira_url url 42 | JiraIntegration.is_valid_url? url 43 | end 44 | 45 | def self.fetch_cards url 46 | issues_xml = JiraIntegration.get(url) 47 | 48 | # TODO: some kind of error instead of broken card 49 | unless issues_xml.include?(". 17 | 18 | module MigrationHelpers 19 | 20 | # TODO: MySQL friendly methods, do some cleanup while porting to other database 21 | def add_foreign_key(from_table, from_column, to_table) 22 | constraint_name = "fk_#{from_table}_#{from_column}" 23 | execute %{alter table #{from_table} add constraint #{constraint_name} foreign key (#{from_column}) references #{to_table}(id)} 24 | end 25 | 26 | def remove_foreign_key(from_table, from_column) 27 | constraint_name = "fk_#{from_table}_#{from_column}" 28 | execute %{alter table #{from_table} drop foreign key #{constraint_name}} 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /lib/taskboard_config.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require 'yaml' 19 | require 'utils' 20 | 21 | class TaskboardConfig 22 | attr_accessor :jira_auth_data; 23 | 24 | def self.instance 25 | if @config.nil? 26 | @config_file_name = "config/taskboard.yml" 27 | @config = YAML.load_file(@config_file_name) 28 | end 29 | @config 30 | 31 | rescue Errno::ENOENT => e 32 | # TODO: log some error? -- but not with 'puts' 33 | @config = TaskboardConfig.new 34 | end 35 | 36 | # only for testing 37 | def self.reset 38 | @config = nil 39 | end 40 | 41 | end 42 | -------------------------------------------------------------------------------- /lib/taskboard_version.rb: -------------------------------------------------------------------------------- 1 | TASKBOARD_VERSION = "10.01.26 Creole" 2 | -------------------------------------------------------------------------------- /lib/url_parser.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | class UrlParser 19 | 20 | URL_REGEXP = /(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/.freeze 21 | 22 | def self.is_url url 23 | not (url =~ URL_REGEXP).nil? 24 | end 25 | 26 | def self.fetch_cards url 27 | url = url.gsub(/\/$/,'') 28 | Array.[](Card.new(:issue_no => url.gsub(/^.*\//,''), :url => url, :name => url)) 29 | end 30 | 31 | end 32 | 33 | -------------------------------------------------------------------------------- /lib/utils.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | def time description = '', &block 19 | start = Time.now 20 | yield 21 | puts "execution time of #{description.empty? ? block.to_s : description}: #{Time.now - start}" 22 | end 23 | 24 | def get_file_as_string(filename) 25 | data = '' 26 | f = File.open(filename, "r") 27 | f.each_line do |line| 28 | data += line 29 | end 30 | return data 31 | end 32 | 33 | -------------------------------------------------------------------------------- /log/report/readme: -------------------------------------------------------------------------------- 1 | Report directory 2 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | The page you were looking for doesn't exist (404) 9 | 21 | 22 | 23 | 24 | 25 |
    26 |

    The page you were looking for doesn't exist.

    27 |

    You may have mistyped the address or the page may have moved.

    28 |
    29 | 30 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | The change you wanted was rejected (422) 9 | 21 | 22 | 23 | 24 | 25 |
    26 |

    The change you wanted was rejected.

    27 |

    Maybe you tried to change something you didn't have access to.

    28 |
    29 | 30 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | We're sorry, but something went wrong (500) 9 | 21 | 22 | 23 | 24 | 25 |
    26 |

    We're sorry, but something went wrong.

    27 |

    We've been notified about this issue and we'll take a look at it shortly.

    28 |
    29 | 30 | -------------------------------------------------------------------------------- /public/dispatch.cgi: -------------------------------------------------------------------------------- 1 | #!c:/ruby/bin/ruby 2 | 3 | require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) 4 | 5 | # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: 6 | # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired 7 | require "dispatcher" 8 | 9 | ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun) 10 | Dispatcher.dispatch -------------------------------------------------------------------------------- /public/dispatch.fcgi: -------------------------------------------------------------------------------- 1 | #!c:/ruby/bin/ruby 2 | # 3 | # You may specify the path to the FastCGI crash log (a log of unhandled 4 | # exceptions which forced the FastCGI instance to exit, great for debugging) 5 | # and the number of requests to process before running garbage collection. 6 | # 7 | # By default, the FastCGI crash log is RAILS_ROOT/log/fastcgi.crash.log 8 | # and the GC period is nil (turned off). A reasonable number of requests 9 | # could range from 10-100 depending on the memory footprint of your app. 10 | # 11 | # Example: 12 | # # Default log path, normal GC behavior. 13 | # RailsFCGIHandler.process! 14 | # 15 | # # Default log path, 50 requests between GC. 16 | # RailsFCGIHandler.process! nil, 50 17 | # 18 | # # Custom log path, normal GC behavior. 19 | # RailsFCGIHandler.process! '/var/log/myapp_fcgi_crash.log' 20 | # 21 | require File.dirname(__FILE__) + "/../config/environment" 22 | require 'fcgi_handler' 23 | 24 | RailsFCGIHandler.process! 25 | -------------------------------------------------------------------------------- /public/dispatch.rb: -------------------------------------------------------------------------------- 1 | #!c:/ruby/bin/ruby 2 | 3 | require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT) 4 | 5 | # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like: 6 | # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired 7 | require "dispatcher" 8 | 9 | ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun) 10 | Dispatcher.dispatch -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/favicon.ico -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/favicon.png -------------------------------------------------------------------------------- /public/images/cognifide_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/cognifide_logo.png -------------------------------------------------------------------------------- /public/images/collapse_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/collapse_all.png -------------------------------------------------------------------------------- /public/images/color_big_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/color_big_off.png -------------------------------------------------------------------------------- /public/images/color_big_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/color_big_on.png -------------------------------------------------------------------------------- /public/images/color_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/color_off.png -------------------------------------------------------------------------------- /public/images/color_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/color_on.png -------------------------------------------------------------------------------- /public/images/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/copy.png -------------------------------------------------------------------------------- /public/images/cross_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/cross_16.png -------------------------------------------------------------------------------- /public/images/cross_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/cross_off.png -------------------------------------------------------------------------------- /public/images/cross_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/cross_on.png -------------------------------------------------------------------------------- /public/images/expand_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/expand_all.png -------------------------------------------------------------------------------- /public/images/hide_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/hide_off.png -------------------------------------------------------------------------------- /public/images/hide_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/hide_on.png -------------------------------------------------------------------------------- /public/images/jquery/jquery.colorpicker.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/jquery/jquery.colorpicker.gif -------------------------------------------------------------------------------- /public/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/loading.gif -------------------------------------------------------------------------------- /public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/logo.png -------------------------------------------------------------------------------- /public/images/open_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/open_off.png -------------------------------------------------------------------------------- /public/images/open_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/open_on.png -------------------------------------------------------------------------------- /public/images/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/plus.png -------------------------------------------------------------------------------- /public/images/rails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/rails.png -------------------------------------------------------------------------------- /public/images/remove_cards_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/remove_cards_off.png -------------------------------------------------------------------------------- /public/images/remove_cards_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/remove_cards_on.png -------------------------------------------------------------------------------- /public/images/rename.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/rename.png -------------------------------------------------------------------------------- /public/images/section_closed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/section_closed.png -------------------------------------------------------------------------------- /public/images/section_opened.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/section_opened.png -------------------------------------------------------------------------------- /public/images/taskboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/taskboard.png -------------------------------------------------------------------------------- /public/images/taskboard_clone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/taskboard_clone.png -------------------------------------------------------------------------------- /public/images/taskboard_plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/taskboard_plus.png -------------------------------------------------------------------------------- /public/images/tip-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/tip-left.png -------------------------------------------------------------------------------- /public/images/tip-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/tip-top.png -------------------------------------------------------------------------------- /public/images/tip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/tip.png -------------------------------------------------------------------------------- /public/images/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/images/warning.png -------------------------------------------------------------------------------- /public/javascripts/footer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 Cognifide 3 | * 4 | * This file is part of Taskboard. 5 | * 6 | * Taskboard is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Taskboard is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | 16 | * You should have received a copy of the GNU General Public License 17 | * along with Taskboard. If not, see . 18 | */ 19 | 20 | (function(){ 21 | 22 | function updateMinHeight(){ 23 | var minHeightWrapper = $(".minHeightWrapper"), 24 | minHeight = $(window).height() - $("h1").outerHeight(true) - 25 | $("#footer").outerHeight(true) - 26 | parseInt(minHeightWrapper.css("margin-bottom")); 27 | minHeightWrapper.css({minHeight: minHeight, overflow: "hidden"}); 28 | } 29 | 30 | $(window).bind('resize', updateMinHeight); 31 | $(document).bind('ready', updateMinHeight); 32 | 33 | })(); 34 | -------------------------------------------------------------------------------- /public/javascripts/lib/juggernaut/jquerynaut.js: -------------------------------------------------------------------------------- 1 | // Simply overwrites prototype specific functions 2 | // with jquery specific versions 3 | 4 | Juggernaut.fn.fire_event = function(fx_name) { 5 | $(document).trigger("juggernaut:" + fx_name); 6 | }; 7 | 8 | Juggernaut.fn.bindToWindow = function() { 9 | $(window).bind("load", this, function(e) { 10 | juggernaut = e.data; 11 | e.data.appendFlashObject(); 12 | }); 13 | }; 14 | 15 | Juggernaut.toJSON = function(hash) { 16 | return $.toJSON(hash) ; 17 | }; 18 | 19 | Juggernaut.parseJSON = function(string) { 20 | return $.parseJSON(string); 21 | }; 22 | 23 | Juggernaut.fn.swf = function(){ 24 | return $('#' + this.options.swf_name)[0]; 25 | }; 26 | 27 | Juggernaut.fn.appendElement = function() { 28 | this.element = $('
    '); 29 | $("body").append(this.element); 30 | }; 31 | 32 | Juggernaut.fn.refreshFlashObject = function(){ 33 | $(this.swf()).remove(); 34 | this.appendFlashObject(); 35 | }; 36 | 37 | Juggernaut.fn.reconnect = function(){ 38 | if(this.options.reconnect_attempts){ 39 | this.attempting_to_reconnect = true; 40 | this.fire_event('reconnect'); 41 | this.logger('Will attempt to reconnect ' + this.options.reconnect_attempts + ' times, the first in ' + (this.options.reconnect_intervals || 3) + ' seconds'); 42 | var self = this; 43 | for(var i=0; i < this.options.reconnect_attempts; i++){ 44 | setTimeout(function(){ 45 | if(!self.is_connected){ 46 | self.logger('Attempting reconnect'); 47 | if(!self.ever_been_connected){ 48 | self.refreshFlashObject(); 49 | } else { 50 | self.connect(); 51 | } 52 | } 53 | }, (this.options.reconnect_intervals || 3) * 1000 * (i + 1)); 54 | 55 | } 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /public/javascripts/lib/juggernaut/json.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | var m = { 3 | '\b': '\\b', 4 | '\t': '\\t', 5 | '\n': '\\n', 6 | '\f': '\\f', 7 | '\r': '\\r', 8 | '"' : '\\"', 9 | '\\': '\\\\' 10 | }, 11 | s = { 12 | 'array': function (x) { 13 | var a = ['['], b, f, i, l = x.length, v; 14 | for (i = 0; i < l; i += 1) { 15 | v = x[i]; 16 | f = s[typeof v]; 17 | if (f) { 18 | v = f(v); 19 | if (typeof v == 'string') { 20 | if (b) { 21 | a[a.length] = ','; 22 | } 23 | a[a.length] = v; 24 | b = true; 25 | } 26 | } 27 | } 28 | a[a.length] = ']'; 29 | return a.join(''); 30 | }, 31 | 'boolean': function (x) { 32 | return String(x); 33 | }, 34 | 'null': function (x) { 35 | return "null"; 36 | }, 37 | 'number': function (x) { 38 | return isFinite(x) ? String(x) : 'null'; 39 | }, 40 | 'object': function (x) { 41 | if (x) { 42 | if (x instanceof Array) { 43 | return s.array(x); 44 | } 45 | var a = ['{'], b, f, i, v; 46 | for (i in x) { 47 | v = x[i]; 48 | f = s[typeof v]; 49 | if (f) { 50 | v = f(v); 51 | if (typeof v == 'string') { 52 | if (b) { 53 | a[a.length] = ','; 54 | } 55 | a.push(s.string(i), ':', v); 56 | b = true; 57 | } 58 | } 59 | } 60 | a[a.length] = '}'; 61 | return a.join(''); 62 | } 63 | return 'null'; 64 | }, 65 | 'string': function (x) { 66 | if (/["\\\x00-\x1f]/.test(x)) { 67 | x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) { 68 | var c = m[b]; 69 | if (c) { 70 | return c; 71 | } 72 | c = b.charCodeAt(); 73 | return '\\u00' + 74 | Math.floor(c / 16).toString(16) + 75 | (c % 16).toString(16); 76 | }); 77 | } 78 | return '"' + x + '"'; 79 | } 80 | }; 81 | 82 | $.toJSON = function(v) { 83 | var f = isNaN(v) ? s[typeof v] : s['number']; 84 | if (f) return f(v); 85 | }; 86 | 87 | $.parseJSON = function(v, safe) { 88 | if (safe === undefined) safe = $.parseJSON.safe; 89 | if (safe && !/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(v)) 90 | return undefined; 91 | return eval('('+v+')'); 92 | }; 93 | 94 | $.parseJSON.safe = false; 95 | 96 | })(jQuery); 97 | 98 | -------------------------------------------------------------------------------- /public/juggernaut/expressinstall.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/juggernaut/expressinstall.swf -------------------------------------------------------------------------------- /public/juggernaut/juggernaut.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/public/juggernaut/juggernaut.swf -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-Agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /public/stylesheets/login.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 Cognifide 3 | * 4 | * This file is part of Taskboard. 5 | * 6 | * Taskboard is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Taskboard is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | 16 | * You should have received a copy of the GNU General Public License 17 | * along with Taskboard. If not, see . 18 | */ 19 | 20 | @import url(generic.css); 21 | 22 | h1 { 23 | width: 400px; 24 | height: 100px; 25 | margin: 20px auto 0; 26 | text-indent: -9999px; 27 | background: url(/images/logo.png) no-repeat scroll 0 0; 28 | } 29 | 30 | fieldset { 31 | margin: 0; 32 | padding: 15px; 33 | background-color: #F8E065; 34 | -moz-border-radius: 10px; 35 | -webkit-border-radius: 10px; 36 | width: 400px; 37 | margin: 20px auto; 38 | } 39 | 40 | fieldset dl dt { 41 | width: 100px; 42 | float: left; 43 | clear: left; 44 | margin-bottom: 10px; 45 | } 46 | 47 | fieldset dl dd { 48 | width: 300px; 49 | float: left; 50 | margin-bottom: 10px; 51 | } 52 | 53 | fieldset dl dd input { 54 | width: 100%; 55 | } 56 | 57 | fieldset input[type=submit] { 58 | float:right; 59 | } 60 | 61 | #notice { 62 | margin: 0; 63 | padding: 15px; 64 | background-color: #F8E065; 65 | -moz-border-radius: 10px; 66 | -webkit-border-radius: 10px; 67 | width: 400px; 68 | margin: 20px auto; 69 | } 70 | -------------------------------------------------------------------------------- /public/stylesheets/print.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 Cognifide 3 | * 4 | * This file is part of Taskboard. 5 | * 6 | * Taskboard is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Taskboard is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | 16 | * You should have received a copy of the GNU General Public License 17 | * along with Taskboard. If not, see . 18 | */ 19 | 20 | @import url(taskboard.css); 21 | 22 | #header { 23 | position: static; 24 | } 25 | 26 | #header #actions { 27 | display: none; 28 | } 29 | 30 | #header #formActions { 31 | display: none; 32 | } 33 | 34 | #taskboard .column { 35 | margin-top : 10px; 36 | } 37 | 38 | #taskboard { 39 | overflow: visible; 40 | } 41 | #taskboard .column .deleteColumn { 42 | display: none; 43 | } 44 | #taskboard .column ol.cards { 45 | min-height: 0 !important; 46 | } 47 | 48 | #taskboard .column ol.cards > li { 49 | border-color: #CCCCCC; 50 | } 51 | 52 | #notifications { 53 | display: none; 54 | } 55 | 56 | #card, #overlay { 57 | display: none; 58 | } 59 | -------------------------------------------------------------------------------- /public/stylesheets/testsuite.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 Cognifide 3 | * 4 | * This file is part of Taskboard. 5 | * 6 | * Taskboard is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Taskboard is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | 16 | * You should have received a copy of the GNU General Public License 17 | * along with Taskboard. If not, see . 18 | */ 19 | 20 | body, div, h1 { font-family: 'trebuchet ms', verdana, arial; margin: 0; padding: 0 } 21 | body {font-size: 10pt; } 22 | h1 { padding: 15px; font-size: large; background-color: #06b; color: white; } 23 | h2 { padding: 10px; background-color: #eee; color: black; margin: 0; font-size: small; font-weight: normal } 24 | 25 | .pass { color: green; } 26 | .fail { color: red; } 27 | p.result { margin-left: 1em; } 28 | 29 | #banner { height: 2em; border-bottom: 1px solid white; } 30 | h2.pass { background-color: green; } 31 | h2.fail { background-color: red; } 32 | 33 | div#fx-tests h4 { 34 | background: red; 35 | } 36 | 37 | div#fx-tests h4.pass { 38 | background: green; 39 | } 40 | 41 | div#fx-tests div.box { 42 | background: red url(data/cow.jpg) no-repeat; 43 | overflow: hidden; 44 | border: 2px solid #000; 45 | } 46 | 47 | div#fx-tests div.overflow { 48 | overflow: visible; 49 | } 50 | 51 | div.inline { 52 | display: inline; 53 | } 54 | 55 | div.autoheight { 56 | height: auto; 57 | } 58 | 59 | div.autowidth { 60 | width: auto; 61 | } 62 | 63 | div.autoopacity { 64 | opacity: auto; 65 | } 66 | 67 | div.largewidth { 68 | width: 100px; 69 | } 70 | 71 | div.largeheight { 72 | height: 100px; 73 | } 74 | 75 | div.largeopacity { 76 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=100); 77 | } 78 | 79 | div.medwidth { 80 | width: 50px; 81 | } 82 | 83 | div.medheight { 84 | height: 50px; 85 | } 86 | 87 | div.medopacity { 88 | opacity: 0.5; 89 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=50); 90 | } 91 | 92 | div.nowidth { 93 | width: 0px; 94 | } 95 | 96 | div.noheight { 97 | height: 0px; 98 | } 99 | 100 | div.noopacity { 101 | opacity: 0; 102 | filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); 103 | } 104 | 105 | div.hidden { 106 | display: none; 107 | } 108 | 109 | div#fx-tests div.widewidth { 110 | background-repeat: repeat-x; 111 | } 112 | 113 | div#fx-tests div.wideheight { 114 | background-repeat: repeat-y; 115 | } 116 | 117 | div#fx-tests div.widewidth.wideheight { 118 | background-repeat: repeat; 119 | } 120 | 121 | div#fx-tests div.noback { 122 | background-image: none; 123 | } 124 | 125 | div.chain, div.chain div { width: 100px; height: 20px; position: relative; float: left; } 126 | div.chain div { position: absolute; top: 0px; left: 0px; } 127 | 128 | div.chain.test { background: red; } 129 | div.chain.test div { background: green; } 130 | 131 | div.chain.out { background: green; } 132 | div.chain.out div { background: red; display: none; } 133 | -------------------------------------------------------------------------------- /script/about: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | $LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info" 4 | require 'commands/about' -------------------------------------------------------------------------------- /script/autospec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | gem 'test-unit', '1.2.3' if RUBY_VERSION.to_f >= 1.9 3 | ENV['RSPEC'] = 'true' # allows autotest to discover rspec 4 | ENV['AUTOTEST'] = 'true' # allows autotest to run w/ color on linux 5 | system((RUBY_PLATFORM =~ /mswin|mingw/ ? 'autotest.bat' : 'autotest'), *ARGV) || 6 | $stderr.puts("Unable to find autotest. Please install ZenTest or fix your PATH") 7 | -------------------------------------------------------------------------------- /script/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/console' 4 | -------------------------------------------------------------------------------- /script/dbconsole: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/dbconsole' 4 | -------------------------------------------------------------------------------- /script/destroy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/destroy' 4 | -------------------------------------------------------------------------------- /script/generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/generate' 4 | -------------------------------------------------------------------------------- /script/performance/benchmarker: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/performance/benchmarker' 4 | -------------------------------------------------------------------------------- /script/performance/profiler: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/performance/profiler' 4 | -------------------------------------------------------------------------------- /script/performance/request: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/performance/request' 4 | -------------------------------------------------------------------------------- /script/plugin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/plugin' 4 | -------------------------------------------------------------------------------- /script/process/inspector: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/process/inspector' 4 | -------------------------------------------------------------------------------- /script/process/reaper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/process/reaper' 4 | -------------------------------------------------------------------------------- /script/process/spawner: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../../config/boot' 3 | require 'commands/process/spawner' 4 | -------------------------------------------------------------------------------- /script/runner: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/runner' 4 | -------------------------------------------------------------------------------- /script/server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require File.dirname(__FILE__) + '/../config/boot' 3 | require 'commands/server' 4 | -------------------------------------------------------------------------------- /script/spin: -------------------------------------------------------------------------------- 1 | /var/www/taskboard/current/script/process/spawner -p 7000 -i 3 -------------------------------------------------------------------------------- /spec/fixtures/columns.yml: -------------------------------------------------------------------------------- 1 | # Sample Project > Kanban board 2 | ############################## 3 | 4 | kanban_backlog_column: 5 | name: 'Backlog' 6 | position: 1 7 | taskboard: kanban_taskboard 8 | 9 | kanban_selected_column: 10 | name: 'Selected (4)' 11 | position: 2 12 | taskboard: kanban_taskboard 13 | 14 | kanban_development_column: 15 | name: 'Development (3)' 16 | position: 3 17 | taskboard: kanban_taskboard 18 | 19 | kanban_done_column: 20 | name: 'Done (4)' 21 | position: 4 22 | taskboard: kanban_taskboard 23 | 24 | kanban_production_column: 25 | name: 'In production :)' 26 | position: 5 27 | taskboard: kanban_taskboard 28 | 29 | 30 | # Sample Project > Scrum board 31 | ############################# 32 | 33 | scrum_story_column: 34 | name: 'Story' 35 | position: 1 36 | taskboard: scrum_taskboard 37 | 38 | scrum_todo_column: 39 | name: 'ToDo' 40 | position: 2 41 | taskboard: scrum_taskboard 42 | 43 | scrum_blocked_column: 44 | name: 'Blocked' 45 | position: 3 46 | taskboard: scrum_taskboard 47 | 48 | scrum_development_column: 49 | name: 'In Development' 50 | position: 4 51 | taskboard: scrum_taskboard 52 | 53 | scrum_test_column: 54 | name: 'Testing' 55 | position: 5 56 | taskboard: scrum_taskboard 57 | 58 | scrum_done_column: 59 | name: 'Done' 60 | position: 6 61 | taskboard: scrum_taskboard 62 | 63 | 64 | # Sample Project > Demo board 65 | ############################ 66 | 67 | demo_tips_column: 68 | name: 'Tips' 69 | position: 1 70 | taskboard: demo_taskboard 71 | 72 | demo_adding_cards_column: 73 | name: 'Adding Cards' 74 | position: 2 75 | taskboard: demo_taskboard 76 | 77 | demo_fun_with_cards_column: 78 | name: 'Fun with cards' 79 | position: 3 80 | taskboard: demo_taskboard 81 | 82 | demo_edit_column: 83 | name: 'Double-click to edit details' 84 | position: 4 85 | taskboard: demo_taskboard 86 | 87 | -------------------------------------------------------------------------------- /spec/fixtures/hours.yml: -------------------------------------------------------------------------------- 1 | # Sample Project > Demo taskboard 2 | ################################ 3 | 4 | demo_hours_card_2days_hours: 5 | date: <%= 2.days.ago.to_s :db %> 6 | left: 5 7 | card: demo_fun_hours_card 8 | 9 | demo_hours_card_1day_hours: 10 | date: <%= 1.day.ago.to_s :db %> 11 | left: 3 12 | card: demo_fun_hours_card 13 | 14 | # Sample Project > Scrum board 15 | ############################## 16 | 17 | # User story 18 | # ----------- 19 | 20 | # 3 days ago 21 | 22 | scrum_animations_card_3days_hours: 23 | date: <%= 3.day.ago.to_s :db %> 24 | left: 8 25 | card: scrum_todo_animations_card 26 | 27 | scrum_help_card_3days_hours: 28 | date: <%= 3.day.ago.to_s :db %> 29 | left: 5 30 | card: scrum_todo_help_card 31 | 32 | scrum_icons_card_3days_hours: 33 | date: <%= 3.day.ago.to_s :db %> 34 | left: 3 35 | card: scrum_blocked_icons_card 36 | 37 | scrum_font_card_3days_hours: 38 | date: <%= 3.day.ago.to_s :db %> 39 | left: 2 40 | card: scrum_development_font_card 41 | 42 | scrum_background_card_3days_hours: 43 | date: <%= 3.day.ago.to_s :db %> 44 | left: 3 45 | card: scrum_test_background_card 46 | 47 | # 2 days ago 48 | 49 | scrum_font_card_2days_hours: 50 | date: <%= 2.days.ago.to_s :db %> 51 | left: 1 52 | card: scrum_development_font_card 53 | 54 | # 1 day ago 55 | 56 | scrum_background_card_1day_hours: 57 | date: <%= 1.day.ago.to_s :db %> 58 | left: 0 59 | card: scrum_test_background_card 60 | 61 | 62 | # Owner story 63 | # ------------ 64 | 65 | # 3 days ago 66 | 67 | scrum_amazing_card_3days_hours: 68 | date: <%= 3.days.ago.to_s :db %> 69 | left: 8 70 | card: scrum_blocked_amazing_card 71 | 72 | scrum_fast_card_3days_hours: 73 | date: <%= 3.days.ago.to_s :db %> 74 | left: 8 75 | card: scrum_development_fast_card 76 | 77 | scrum_intuitive_card_3days_hours: 78 | date: <%= 3.days.ago.to_s :db %> 79 | left: 12 80 | card: scrum_development_intuitive_card 81 | 82 | scrum_real_card_3days_hours: 83 | date: <%= 3.days.ago.to_s :db %> 84 | left: 5 85 | card: scrum_done_real_card 86 | 87 | # 2 days ago 88 | 89 | scrum_fast_card_2days_hours: 90 | date: <%= 2.days.ago.to_s :db %> 91 | left: 3 92 | card: scrum_development_fast_card 93 | 94 | scrum_intuitive_card_2days_hours: 95 | date: <%= 2.days.ago.to_s :db %> 96 | left: 8 97 | card: scrum_development_intuitive_card 98 | 99 | # 1 day ago 100 | 101 | scrum_intuitive_card_1day_hours: 102 | date: <%= 1.day.ago.to_s :db %> 103 | left: 2 104 | card: scrum_development_intuitive_card 105 | 106 | scrum_real_card_1day_hours: 107 | date: <%= 1.day.ago.to_s :db %> 108 | left: 0 109 | card: scrum_done_real_card 110 | 111 | -------------------------------------------------------------------------------- /spec/fixtures/jira-issue-01.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Some Issue Tracking 4 | http://some.issue.tracker.com/jira 5 | Fake issue tracker 6 | en-gb 7 | 8 | [ISSUE-12] Table name case 9 | http://jira.example.com/jira/browse/ISSUE-12 10 | Description of the issue. 11 | ISSUE-12 12 | Table name case 13 | Software Bug 14 | Standard 15 | Closed 16 | Fixed 17 | Joe Texas 18 | Joe Texas 19 | 20 | Wed, 10 Sep 2008 15:06:21 +0100 (BST) 21 | Wed, 17 Sep 2008 17:43:30 +0100 (BST) 22 | 23 | 1.1 24 | 1.3 25 | 26 | The Software 27 | 28 | 0 29 | 30 | 31 | Question? 32 | Answer. 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Story points 45 | 46 | 47 | 48 | 49 | 50 | 51 | Iteration Scheduled 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /spec/fixtures/projects.yml: -------------------------------------------------------------------------------- 1 | sample_project: 2 | name: "Sample Taskboards" 3 | 4 | -------------------------------------------------------------------------------- /spec/fixtures/rows.yml: -------------------------------------------------------------------------------- 1 | # Sample Project > Kanban board 2 | ############################## 3 | 4 | kanban_row: 5 | name: 'Row' 6 | position: 1 7 | taskboard: kanban_taskboard 8 | 9 | # Sample Project > Scrum board 10 | ############################# 11 | 12 | scrum_user_row: 13 | name: 'User Story Row' 14 | position: 1 15 | taskboard: scrum_taskboard 16 | 17 | scrum_owner_row: 18 | name: 'Owner Story Row' 19 | position: 2 20 | taskboard: scrum_taskboard 21 | 22 | # Sample Project > Demo board 23 | ############################ 24 | 25 | demo_first_row: 26 | name: 'First row' 27 | position: 1 28 | taskboard: demo_taskboard 29 | 30 | demo_second_row: 31 | name: 'Second row' 32 | position: 2 33 | taskboard: demo_taskboard 34 | 35 | -------------------------------------------------------------------------------- /spec/fixtures/taggings.yml: -------------------------------------------------------------------------------- 1 | # Sample Project > Demo taskboard 2 | ################################ 3 | 4 | demo_awesome_tagging: 5 | tag: awesome_tag 6 | taggable: demo_fun_tags_card 7 | taggable_type: 'Card' 8 | 9 | demo_amazing_tagging: 10 | tag: amazing_tag 11 | taggable: demo_fun_tags_card 12 | taggable_type: 'Card' 13 | 14 | demo_cool_tagging: 15 | tag: cool_tag 16 | taggable: demo_fun_tags_card 17 | taggable_type: 'Card' 18 | 19 | demo_smile_tagging: 20 | tag: smile_tag 21 | taggable: demo_fun_tags_card 22 | taggable_type: 'Card' 23 | 24 | 25 | # Sample Project > Kanban taskboard 26 | ################################## 27 | 28 | kanban_development_tom_tagging: 29 | tag: tom_tag 30 | taggable: kanban_development_documentation_card 31 | taggable_type: 'Card' 32 | 33 | kanban_development_bob_tagging: 34 | tag: bob_tag 35 | taggable: kanban_development_amazing_card 36 | taggable_type: 'Card' 37 | 38 | kanban_development_check_bob_tagging: 39 | tag: check_tag 40 | taggable: kanban_development_amazing_card 41 | taggable_type: 'Card' 42 | 43 | kanban_development_joe_tagging: 44 | tag: joe_tag 45 | taggable: kanban_development_bug_card 46 | taggable_type: 'Card' 47 | 48 | kanban_development_check_joe_tagging: 49 | tag: check_tag 50 | taggable: kanban_development_bug_card 51 | taggable_type: 'Card' 52 | 53 | kanban_done_joe_tagging: 54 | tag: joe_tag 55 | taggable: kanban_done_bug_card 56 | taggable_type: 'Card' 57 | 58 | kanban_done_bob_tagging: 59 | tag: bob_tag 60 | taggable: kanban_done_amazing_card 61 | taggable_type: 'Card' 62 | 63 | kanban_done_merged_bob_tagging: 64 | tag: merged_tag 65 | taggable: kanban_done_amazing_card 66 | taggable_type: 'Card' 67 | 68 | kanban_production_bob_tagging: 69 | tag: bob_tag 70 | taggable: kanban_production_real_card 71 | taggable_type: 'Card' 72 | 73 | kanban_production_tom_tagging: 74 | tag: tom_tag 75 | taggable: kanban_production_documentation_card 76 | taggable_type: 'Card' 77 | 78 | 79 | # Sample Project > Scrum taskboard 80 | ################################# 81 | 82 | scrum_story_3_points_tagging: 83 | tag: story_points_3_tag 84 | taggable: scrum_story_user_card 85 | taggable_type: 'Card' 86 | 87 | scrum_story_5_points_tagging: 88 | tag: story_points_5_tag 89 | taggable: scrum_story_owner_card 90 | taggable_type: 'Card' 91 | 92 | scrum_blocked_desing_tagging: 93 | tag: needs_design_tag 94 | taggable: scrum_blocked_icons_card 95 | taggable_type: 'Card' 96 | 97 | scrum_blocked_amazing_tagging: 98 | tag: needs_feedback_tag 99 | taggable: scrum_blocked_amazing_card 100 | taggable_type: 'Card' 101 | 102 | scrum_development_bob_tagging: 103 | tag: bob_tag 104 | taggable: scrum_development_font_card 105 | taggable_type: 'Card' 106 | 107 | scrum_test_bob_tagging: 108 | tag: bob_tag 109 | taggable: scrum_test_background_card 110 | taggable_type: 'Card' 111 | 112 | scrum_development_joe_tagging: 113 | tag: joe_tag 114 | taggable: scrum_development_fast_card 115 | taggable_type: 'Card' 116 | 117 | scrum_development_tom_tagging: 118 | tag: tom_tag 119 | taggable: scrum_development_intuitive_card 120 | taggable_type: 'Card' 121 | 122 | scrum_done_tom_tagging: 123 | tag: tom_tag 124 | taggable: scrum_done_real_card 125 | taggable_type: 'Card' 126 | 127 | -------------------------------------------------------------------------------- /spec/fixtures/tags.yml: -------------------------------------------------------------------------------- 1 | # Sample Project > Demo taskboard 2 | ################################ 3 | 4 | awesome_tag: 5 | name: 'awesome' 6 | 7 | amazing_tag: 8 | name: 'amazing' 9 | 10 | cool_tag: 11 | name: 'cool' 12 | 13 | smile_tag: 14 | name: ':)' 15 | 16 | 17 | # Sample Project > Kanban taskboard 18 | ################################## 19 | 20 | bob_tag: 21 | name: 'Bob' 22 | 23 | joe_tag: 24 | name: 'Joe' 25 | 26 | tom_tag: 27 | name: 'Tom' 28 | 29 | check_tag: 30 | name: 'Check me!' 31 | 32 | merged_tag: 33 | name: 'merged' 34 | 35 | 36 | # Sample Project > Scrum taskboard 37 | ################################## 38 | 39 | needs_design_tag: 40 | name: 'designs needed' 41 | 42 | needs_feedback_tag: 43 | name: 'feedback needed' 44 | 45 | story_points_5_tag: 46 | name: '5 SP' 47 | 48 | story_points_3_tag: 49 | name: '3 SP' 50 | 51 | -------------------------------------------------------------------------------- /spec/fixtures/taskboards.yml: -------------------------------------------------------------------------------- 1 | # Sample taskboards 2 | #################### 3 | 4 | kanban_taskboard: 5 | name: "Kanban Board" 6 | project: sample_project 7 | 8 | scrum_taskboard: 9 | name: "Scrum Sprint Board" 10 | project: sample_project 11 | 12 | demo_taskboard: 13 | name: "Demo: Taskboard Features" 14 | project: sample_project 15 | 16 | -------------------------------------------------------------------------------- /spec/fixtures/users.yml: -------------------------------------------------------------------------------- 1 | test_editor: 2 | username: "test_editor" 3 | salt: "salt" 4 | hashed_password: <%= User.encrypted_password("editor_password", "salt") %> 5 | editor: true 6 | 7 | test_viewer: 8 | username: "test_viewer" 9 | salt: "salt" 10 | hashed_password: <%= User.encrypted_password("viewer_password", "salt") %> 11 | 12 | editor: 13 | username: "editor" 14 | salt: "salt" 15 | hashed_password: <%= User.encrypted_password("password", "salt") %> 16 | editor: true 17 | 18 | viewer: 19 | username: "viewer" 20 | salt: "salt" 21 | hashed_password: <%= User.encrypted_password("password", "salt") %> 22 | 23 | -------------------------------------------------------------------------------- /spec/helpers/application_helper_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | 20 | include ApplicationHelper 21 | 22 | describe ApplicationHelper do 23 | 24 | it "should make time" do 25 | make_time("2008-10-12").should eql(1223762400) 26 | make_time("2006-04-29").should eql(1146261600) 27 | make_time("2014-07-04").should eql(1404424800) 28 | end 29 | 30 | it "should build proper javascript data structure from empty burndown hash" do 31 | burndown = burndown(Card.new) 32 | burndown.should include_text("[]") 33 | end 34 | 35 | it "should build proper javascript data structure from not-empty burndown hash" do 36 | card = Card.new 37 | 38 | card.hours << Hour.new(:date => 5.days.ago, :left => 13) 39 | card.hours << Hour.new(:date => 3.days.ago, :left => 8) 40 | card.hours << Hour.new(:date => 1.day.ago, :left => 3) 41 | 42 | burndown(card).should match(/\[\[\d+,\s13\],\s\[\d+,\s13\],\s\[\d+,\s8\],\s\[\d+,\s8\],\s\[\d+,\s3\],\s\[\d+,\s3\]\]/) 43 | end 44 | 45 | it "should build proper javascript timestamp" do 46 | card = Card.new 47 | 48 | tics = make_time("2008-12-18").to_i * 1000 49 | 50 | card.hours << Hour.new(:date => "2008-12-18", :left => 10) 51 | 52 | burndown(card).should include(tics.to_s) 53 | end 54 | 55 | end 56 | -------------------------------------------------------------------------------- /spec/helpers/card_helper_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | 20 | describe CardHelper do 21 | 22 | #Delete this example and add some real ones or delete this file 23 | it "should be included in the object returned by #helper" do 24 | included_modules = (class << helper; self; end).send :included_modules 25 | included_modules.should include(CardHelper) 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /spec/helpers/login_helper_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | 20 | describe LoginHelper do 21 | 22 | #Delete this example and add some real ones or delete this file 23 | it "should be included in the object returned by #helper" do 24 | included_modules = (class << helper; self; end).send :included_modules 25 | included_modules.should include(LoginHelper) 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /spec/helpers/project_helper_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | 20 | describe ProjectHelper do 21 | 22 | #Delete this example and add some real ones or delete this file 23 | it "should be included in the object returned by #helper" do 24 | included_modules = (class << helper; self; end).send :included_modules 25 | included_modules.should include(ProjectHelper) 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /spec/helpers/taskboard_helper_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | 20 | describe TaskboardHelper do 21 | 22 | end 23 | -------------------------------------------------------------------------------- /spec/javascripts/fixtures/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Home | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /spec/javascripts/fixtures/screw.css: -------------------------------------------------------------------------------- 1 | html { 2 | padding: 0.5em; 3 | font-family: Georgia, serif; 4 | background: #EDEBD5; 5 | } 6 | 7 | li { 8 | list-style-type: none; 9 | } 10 | 11 | .focused { 12 | background-color: #F4F2E4; 13 | } 14 | 15 | .focused * { 16 | opacity: 1.0; 17 | } 18 | 19 | h1, h2, p { 20 | opacity: 0.4; 21 | } 22 | 23 | .describes { 24 | padding-left: 0; 25 | } 26 | 27 | .describes h1 { 28 | font-size: 1.1em; 29 | color: #877C21; 30 | line-height: 1.8em; 31 | margin: 0pt 0pt 0.6em; 32 | border-bottom: 1px solid transparent; 33 | } 34 | 35 | .describes h1:hover { 36 | cursor: pointer; 37 | color: #000; 38 | background-color: #F4F2E4; 39 | border-bottom: 1px solid #9A8E51; 40 | } 41 | 42 | .describes .describe { 43 | margin-left: 0.6em; 44 | padding-left: 0.6em; 45 | border: 1px dashed #999; 46 | } 47 | 48 | .describes .describe .its {} 49 | 50 | .describes .describe .its .it { 51 | list-style-type: lower-roman; 52 | list-style-position: outside; 53 | } 54 | 55 | .describes .describe .its .it h2 { 56 | font-weight: normal; 57 | font-style: italic; 58 | padding-left: 0.5em; 59 | font-size: 1.0em; 60 | color: #877C21; 61 | line-height: 1.8em; 62 | margin: 0 0 0.5em; 63 | border-bottom: 1px solid transparent; 64 | } 65 | 66 | .describes .describe .its .it.enqueued h2 { 67 | background-color: #CC6600; 68 | color: white !important; 69 | } 70 | 71 | .describes .describe .its .it.passed h2 { 72 | background-color: #5A753D; 73 | color: white !important; 74 | } 75 | 76 | .describes .describe .its .it.failed h2 { 77 | background-color: #993300; 78 | color: white !important; 79 | } 80 | 81 | .describes .describe .its .it.failed p { 82 | margin-left: 1em; 83 | color: #993300; 84 | } 85 | 86 | .describes .describe .its .it h2:hover { 87 | cursor: pointer; 88 | color: #000 !important; 89 | border-bottom: 1px solid #9A8E51; 90 | } 91 | -------------------------------------------------------------------------------- /spec/javascripts/fixtures/utils.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Utils | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /spec/javascripts/spec_helper.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2009 Cognifide 3 | * 4 | * This file is part of Taskboard. 5 | * 6 | * Taskboard is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Taskboard is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | 16 | * You should have received a copy of the GNU General Public License 17 | * along with Taskboard. If not, see . 18 | */ 19 | 20 | // Use this file to require common dependencies or to setup useful test functions. 21 | 22 | Screw.Matchers["be_function"] = { 23 | match: function(expected, actual) { 24 | return typeof actual == "function"; 25 | }, 26 | failure_message: function(expected, actual, not) { 27 | return 'expected ' + $.print(actual) + (not ? ' not' : '') + ' to be function'; 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /spec/lib/taskboard_config_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | require 'yaml' 20 | require 'taskboard_config' 21 | 22 | describe TaskboardConfig do 23 | 24 | it "should parse yml file" do 25 | conf = TaskboardConfig.new 26 | conf.jira_auth_data = {"some.url.com" => { "os_password" => "pass", "os_username" => "user" } } 27 | 28 | YAML.should_receive(:load_file).and_return(conf) 29 | 30 | TaskboardConfig.reset 31 | TaskboardConfig.instance.jira_auth_data["some.url.com"]["os_password"].should eql("pass") 32 | TaskboardConfig.instance.jira_auth_data["some.url.com"]["os_username"].should eql("user") 33 | end 34 | 35 | it "should log errors" do 36 | YAML.should_receive(:load_file).and_raise(Errno::ENOENT) 37 | 38 | TaskboardConfig.reset 39 | TaskboardConfig.instance.jira_auth_data.nil?.should be_true 40 | end 41 | 42 | end 43 | 44 | -------------------------------------------------------------------------------- /spec/lib/taskboard_version_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | require 'taskboard_version' 20 | 21 | describe TASKBOARD_VERSION do 22 | 23 | it "should be a text with correct format" do 24 | TASKBOARD_VERSION.should_not be_nil 25 | TASKBOARD_VERSION.should be_a(String) 26 | TASKBOARD_VERSION.should match(/^[0-9]{2}\.[0-9]{2}(\.[0-9]{2})?.*/) 27 | end 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /spec/lib/url_parser_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | require 'url_parser' 20 | 21 | describe UrlParser, "while helping with url recognition" do 22 | 23 | it "should recognize valid urls" do 24 | [ 'https://jira.cognifide.com/jira/browse/TASKBOARD-2', 25 | 'https://localhost:3000/app', 'http://google.com', 26 | 'http://google.com/', 'http://192.168.1.1', 27 | 'http://127.0.0.1:6363', 'http://127.0.0.1:6363', 28 | 'http://192.168.1.1/jira'].each do |url| 29 | UrlParser.is_url(url).should be_true 30 | end 31 | 32 | UrlParser.is_url('My new card!').should be_false 33 | end 34 | 35 | end 36 | 37 | describe UrlParser do 38 | 39 | it "should response to :fetch_cards method" do 40 | UrlParser.should respond_to(:fetch_cards) 41 | end 42 | 43 | it "should fetch a card for given url" do 44 | check_card_name('https://jira.cognifide.com/jira/browse/TASKBOARD-2', 'https://jira.cognifide.com/jira/browse/TASKBOARD-2', 'TASKBOARD-2'); 45 | check_card_name('https://jira.cognifide.com/jira/browse/TASKBOARD-3/', 'https://jira.cognifide.com/jira/browse/TASKBOARD-3','TASKBOARD-3'); 46 | end 47 | 48 | private 49 | 50 | def check_card_name(based_url, url, name) 51 | cards = UrlParser.fetch_cards(based_url) 52 | cards.size.should eql(1) 53 | cards.last.name.should eql(url) 54 | cards.last.issue_no.should eql(name) 55 | cards.last.url.should eql(url) 56 | end 57 | 58 | end 59 | -------------------------------------------------------------------------------- /spec/lib/utils_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | require 'utils' 20 | 21 | describe "Utils" do 22 | 23 | context "time function" do 24 | 25 | it "should print execution time of given block" do 26 | self.should_receive(:puts).with(/execution time of test/) 27 | time 'test' do 28 | (1..1000).each { } 29 | end 30 | end 31 | 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /spec/models/hour_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | 20 | describe Hour do 21 | before(:each) do 22 | @valid_attributes = { 23 | :date => Time.new, 24 | :left => 3 25 | } 26 | end 27 | 28 | it "should create a new instance given valid attributes" do 29 | Hour.create!(@valid_attributes) 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/models/project_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | 20 | describe Project do 21 | fixtures :projects, :taskboards 22 | 23 | it "should create a new instance with given name" do 24 | Project.create!(:name => "Test Project") 25 | end 26 | 27 | it "should not be valid with empty name" do 28 | [nil, "", " ", " " ].each { |invalid_name| 29 | project = Project.new(:name => invalid_name) 30 | project.should_not be_valid 31 | } 32 | end 33 | 34 | it "should have correct number of taskboards assigned" do 35 | project = projects(:sample_project) 36 | project.should have_at_least(1).taskboard 37 | end 38 | 39 | it "should define default project's name" do 40 | Project::DEFAULT_NAME.should_not be_empty 41 | end 42 | 43 | end 44 | -------------------------------------------------------------------------------- /spec/models/row_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | 20 | describe Row do 21 | fixtures :taskboards 22 | 23 | before(:each) do 24 | @valid_attributes = { 25 | :name => 'TODO', 26 | :position => 1, 27 | :taskboard_id => taskboards(:scrum_taskboard).id 28 | } 29 | end 30 | 31 | it "should create a new instance given valid attributes" do 32 | Row.create!(@valid_attributes) 33 | end 34 | end 35 | 36 | describe Row, "while working with database" do 37 | fixtures :taskboards, :columns, :rows, :cards 38 | 39 | it "should have non-empty collection of rows" do 40 | Row.find(:all).should_not be_empty 41 | end 42 | 43 | it "should allow inserting new row at given position" do 44 | @taskboard = taskboards(:scrum_taskboard) 45 | @row_1 = rows(:scrum_user_row) 46 | @row_2 = rows(:scrum_owner_row) 47 | row = Row.create!(:name => 'new row', :taskboard => @taskboard) 48 | row.insert_at(2) 49 | row.higher_item.should eql(@row_1) 50 | row.lower_item.should eql(@row_2) 51 | end 52 | 53 | it "should define default name" do 54 | Row::DEFAULT_NAME.should_not be_empty 55 | end 56 | 57 | it "should contain valid number of cards" do 58 | row = rows(:demo_first_row) 59 | row.should have_at_least(1).card 60 | end 61 | 62 | it "should get cards in given row" do 63 | column = columns(:scrum_todo_column) 64 | row = rows(:scrum_owner_row) 65 | row.cards.in_column(column).length.should < row.cards.length 66 | end 67 | 68 | it "should clone name and position" do 69 | row = rows(:demo_first_row) 70 | clonned = row.clone 71 | 72 | clonned.class.should be(Row) 73 | clonned.should_not eql(row) 74 | clonned.name.should eql(row.name) 75 | clonned.position.should eql(row.position) 76 | clonned.taskboard_id.should eql(row.taskboard_id) 77 | 78 | clonned = row.clone 234 79 | 80 | clonned.class.should be(Row) 81 | clonned.should_not eql(row) 82 | clonned.name.should eql(row.name) 83 | clonned.position.should eql(row.position) 84 | clonned.taskboard_id.should eql(234) 85 | end 86 | 87 | end 88 | -------------------------------------------------------------------------------- /spec/models/user_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Cognifide 2 | # 3 | # This file is part of Taskboard. 4 | # 5 | # Taskboard is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # Taskboard is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with Taskboard. If not, see . 17 | 18 | require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') 19 | 20 | describe User do 21 | fixtures :users 22 | 23 | it "should save hashed password when password is set" do 24 | user = User.new(:username => "testuser", :password => "testpassword") 25 | user.hashed_password.should_not be_empty 26 | user.hashed_password.should_not eql("testpassword") 27 | user.password.should eql("testpassword") 28 | 29 | user.valid?.should eql(true) 30 | end 31 | 32 | it "should not allow to save user without password" do 33 | user = User.new(:username => "testuser") 34 | user.valid?.should eql(false) 35 | end 36 | 37 | it "should not allow creating second user with same username" do 38 | user1 = User.new(:username => "name", :password => "testpassword") 39 | user1.save 40 | user2 = User.new(:username => "name", :password => "testpassword") 41 | user2.valid?.should eql(false) 42 | end 43 | 44 | it "should create some salt" do 45 | salt1 = User.new(:username => "name", :password => "password").salt 46 | salt1.should_not be_empty 47 | salt2 = User.new(:username => "name", :password => "password").salt 48 | salt2.should_not be_empty 49 | salt2.should_not eql(salt1) 50 | end 51 | 52 | 53 | it "should authenticate user if correct password is given" do 54 | user = users(:test_editor) 55 | authenticated_user = User.authenticate(user.username, "editor_password") 56 | authenticated_user.should_not be_nil 57 | authenticated_user.should eql(user) 58 | end 59 | 60 | it "should authenticate user if wrong password is given" do 61 | user = users(:test_editor) 62 | authenticated_user = User.authenticate(user.username, "wrongpassword") 63 | authenticated_user.should be_nil 64 | end 65 | 66 | it "should authenticate user if wrong username is given" do 67 | authenticated_user = User.authenticate("fakeuser", "password") 68 | authenticated_user.should be_nil 69 | end 70 | end 71 | 72 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_list/README: -------------------------------------------------------------------------------- 1 | ActsAsList 2 | ========== 3 | 4 | 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. 5 | 6 | 7 | Example 8 | ======= 9 | 10 | class TodoList < ActiveRecord::Base 11 | has_many :todo_items, :order => "position" 12 | end 13 | 14 | class TodoItem < ActiveRecord::Base 15 | belongs_to :todo_list 16 | acts_as_list :scope => :todo_list 17 | end 18 | 19 | todo_list.first.move_to_bottom 20 | todo_list.last.move_higher 21 | 22 | 23 | Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license -------------------------------------------------------------------------------- /vendor/plugins/acts_as_list/init.rb: -------------------------------------------------------------------------------- 1 | $:.unshift "#{File.dirname(__FILE__)}/lib" 2 | require 'active_record/acts/list' 3 | ActiveRecord::Base.class_eval { include ActiveRecord::Acts::List } 4 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2006 Jonathan Viney 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake' 2 | require 'rake/testtask' 3 | require 'rake/rdoctask' 4 | 5 | desc 'Default: run unit tests.' 6 | task :default => :test 7 | 8 | desc 'Test the acts_as_taggable_on_steroids plugin.' 9 | Rake::TestTask.new(:test) do |t| 10 | t.libs << 'lib' 11 | t.pattern = 'test/**/*_test.rb' 12 | t.verbose = true 13 | end 14 | 15 | desc 'Generate documentation for the acts_as_taggable_on_steroids plugin.' 16 | Rake::RDocTask.new(:rdoc) do |rdoc| 17 | rdoc.rdoc_dir = 'rdoc' 18 | rdoc.title = 'Acts As Taggable On Steroids' 19 | rdoc.options << '--line-numbers' << '--inline-source' 20 | rdoc.rdoc_files.include('README') 21 | rdoc.rdoc_files.include('lib/**/*.rb') 22 | end 23 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/generators/acts_as_taggable_migration/acts_as_taggable_migration_generator.rb: -------------------------------------------------------------------------------- 1 | class ActsAsTaggableMigrationGenerator < Rails::Generator::Base 2 | def manifest 3 | record do |m| 4 | m.migration_template 'migration.rb', 'db/migrate' 5 | end 6 | end 7 | 8 | def file_name 9 | "acts_as_taggable_migration" 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/generators/acts_as_taggable_migration/templates/migration.rb: -------------------------------------------------------------------------------- 1 | class ActsAsTaggableMigration < ActiveRecord::Migration 2 | def self.up 3 | create_table :tags do |t| 4 | t.column :name, :string 5 | end 6 | 7 | create_table :taggings do |t| 8 | t.column :tag_id, :integer 9 | t.column :taggable_id, :integer 10 | 11 | # You should make sure that the column created is 12 | # long enough to store the required class names. 13 | t.column :taggable_type, :string 14 | 15 | t.column :created_at, :datetime 16 | end 17 | 18 | add_index :taggings, :tag_id 19 | add_index :taggings, [:taggable_id, :taggable_type] 20 | end 21 | 22 | def self.down 23 | drop_table :taggings 24 | drop_table :tags 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/init.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/lib/acts_as_taggable' 2 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/lib/tag.rb: -------------------------------------------------------------------------------- 1 | class Tag < ActiveRecord::Base 2 | has_many :taggings, :dependent => :destroy 3 | 4 | validates_presence_of :name 5 | validates_uniqueness_of :name 6 | 7 | cattr_accessor :destroy_unused 8 | self.destroy_unused = false 9 | 10 | # LIKE is used for cross-database case-insensitivity 11 | def self.find_or_create_with_like_by_name(name) 12 | find(:first, :conditions => ["name LIKE ?", name]) || create(:name => name) 13 | end 14 | 15 | def ==(object) 16 | super || (object.is_a?(Tag) && name == object.name) 17 | end 18 | 19 | def to_s 20 | name 21 | end 22 | 23 | def count 24 | read_attribute(:count).to_i 25 | end 26 | 27 | class << self 28 | # Calculate the tag counts for all tags. 29 | # :start_at - Restrict the tags to those created after a certain time 30 | # :end_at - Restrict the tags to those created before a certain time 31 | # :conditions - A piece of SQL conditions to add to the query 32 | # :limit - The maximum number of tags to return 33 | # :order - A piece of SQL to order by. Eg 'count desc' or 'taggings.created_at desc' 34 | # :at_least - Exclude tags with a frequency less than the given value 35 | # :at_most - Exclude tags with a frequency greater than the given value 36 | def counts(options = {}) 37 | find(:all, options_for_counts(options)) 38 | end 39 | 40 | def options_for_counts(options = {}) 41 | options.assert_valid_keys :start_at, :end_at, :conditions, :at_least, :at_most, :order, :limit, :joins 42 | options = options.dup 43 | 44 | start_at = sanitize_sql(["#{Tagging.table_name}.created_at >= ?", options.delete(:start_at)]) if options[:start_at] 45 | end_at = sanitize_sql(["#{Tagging.table_name}.created_at <= ?", options.delete(:end_at)]) if options[:end_at] 46 | 47 | conditions = [ 48 | options.delete(:conditions), 49 | start_at, 50 | end_at 51 | ].compact 52 | 53 | conditions = conditions.any? ? conditions.join(' AND ') : nil 54 | 55 | joins = ["INNER JOIN #{Tagging.table_name} ON #{Tag.table_name}.id = #{Tagging.table_name}.tag_id"] 56 | joins << options.delete(:joins) if options[:joins] 57 | 58 | at_least = sanitize_sql(['COUNT(*) >= ?', options.delete(:at_least)]) if options[:at_least] 59 | at_most = sanitize_sql(['COUNT(*) <= ?', options.delete(:at_most)]) if options[:at_most] 60 | having = [at_least, at_most].compact.join(' AND ') 61 | group_by = "#{Tag.table_name}.id, #{Tag.table_name}.name HAVING COUNT(*) > 0" 62 | group_by << " AND #{having}" unless having.blank? 63 | 64 | { :select => "#{Tag.table_name}.id, #{Tag.table_name}.name, COUNT(*) AS count", 65 | :joins => joins.join(" "), 66 | :conditions => conditions, 67 | :group => group_by 68 | }.update(options) 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/lib/tag_counts_extension.rb: -------------------------------------------------------------------------------- 1 | # Deprecated 2 | module TagCountsExtension #:nodoc: 3 | end 4 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/lib/tag_list.rb: -------------------------------------------------------------------------------- 1 | class TagList < Array 2 | cattr_accessor :delimiter 3 | self.delimiter = ',' 4 | 5 | def initialize(*args) 6 | add(*args) 7 | end 8 | 9 | # Add tags to the tag_list. Duplicate or blank tags will be ignored. 10 | # 11 | # tag_list.add("Fun", "Happy") 12 | # 13 | # Use the :parse option to add an unparsed tag string. 14 | # 15 | # tag_list.add("Fun, Happy", :parse => true) 16 | def add(*names) 17 | extract_and_apply_options!(names) 18 | concat(names) 19 | clean! 20 | self 21 | end 22 | 23 | # Remove specific tags from the tag_list. 24 | # 25 | # tag_list.remove("Sad", "Lonely") 26 | # 27 | # Like #add, the :parse option can be used to remove multiple tags in a string. 28 | # 29 | # tag_list.remove("Sad, Lonely", :parse => true) 30 | def remove(*names) 31 | extract_and_apply_options!(names) 32 | delete_if { |name| names.include?(name) } 33 | self 34 | end 35 | 36 | # Toggle the presence of the given tags. 37 | # If a tag is already in the list it is removed, otherwise it is added. 38 | def toggle(*names) 39 | extract_and_apply_options!(names) 40 | 41 | names.each do |name| 42 | include?(name) ? delete(name) : push(name) 43 | end 44 | 45 | clean! 46 | self 47 | end 48 | 49 | # Transform the tag_list into a tag string suitable for edting in a form. 50 | # The tags are joined with TagList.delimiter and quoted if necessary. 51 | # 52 | # tag_list = TagList.new("Round", "Square,Cube") 53 | # tag_list.to_s # 'Round, "Square,Cube"' 54 | def to_s 55 | clean! 56 | 57 | map do |name| 58 | name.include?(delimiter) ? "\"#{name}\"" : name 59 | end.join(delimiter.ends_with?(" ") ? delimiter : "#{delimiter} ") 60 | end 61 | 62 | private 63 | # Remove whitespace, duplicates, and blanks. 64 | def clean! 65 | reject!(&:blank?) 66 | map!(&:strip) 67 | uniq! 68 | end 69 | 70 | def extract_and_apply_options!(args) 71 | options = args.last.is_a?(Hash) ? args.pop : {} 72 | options.assert_valid_keys :parse 73 | 74 | if options[:parse] 75 | args.map! { |a| self.class.from(a) } 76 | end 77 | 78 | args.flatten! 79 | end 80 | 81 | class << self 82 | # Returns a new TagList using the given tag string. 83 | # 84 | # tag_list = TagList.from("One , Two, Three") 85 | # tag_list # ["One", "Two", "Three"] 86 | def from(source) 87 | returning new do |tag_list| 88 | 89 | case source 90 | when Array 91 | tag_list.add(source) 92 | else 93 | string = source.to_s.dup 94 | 95 | # Parse the quoted tags 96 | [ 97 | /\s*#{delimiter}\s*(['"])(.*?)\1\s*/, 98 | /^\s*(['"])(.*?)\1\s*#{delimiter}?/ 99 | ].each do |re| 100 | string.gsub!(re) { tag_list << $2; "" } 101 | end 102 | 103 | tag_list.add(string.split(delimiter)) 104 | end 105 | end 106 | end 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/lib/tagging.rb: -------------------------------------------------------------------------------- 1 | class Tagging < ActiveRecord::Base #:nodoc: 2 | belongs_to :tag 3 | belongs_to :taggable, :polymorphic => true 4 | 5 | def after_destroy 6 | if Tag.destroy_unused 7 | if tag.taggings.count.zero? 8 | tag.destroy 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /vendor/plugins/acts_as_taggable_on_steroids/lib/tags_helper.rb: -------------------------------------------------------------------------------- 1 | module TagsHelper 2 | # See the README for an example using tag_cloud. 3 | def tag_cloud(tags, classes) 4 | return if tags.empty? 5 | 6 | max_count = tags.sort_by(&:count).last.count.to_f 7 | 8 | tags.each do |tag| 9 | index = ((tag.count / max_count) * (classes.size - 1)).round 10 | yield tag, classes[index] 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2009 Relevance, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/LICENSE-Screw.Unit: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008 Nick Kallen 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/LICENSE-Smoke: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008 Andy Kent 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/Rakefile: -------------------------------------------------------------------------------- 1 | ENV["BLUE_RIDGE_PREFIX"] = File.dirname(__FILE__) 2 | import File.dirname(__FILE__) + '/tasks/javascript_testing_tasks.rake' 3 | 4 | gem "spicycode-micronaut", ">= 0.2.4" 5 | require 'micronaut' 6 | require 'micronaut/rake_task' 7 | 8 | namespace :test do 9 | desc "Run all micronaut examples using rcov" 10 | Micronaut::RakeTask.new :rubies do |t| 11 | t.pattern = "spec/rubies/**/*_spec.rb" 12 | end 13 | end 14 | 15 | task :default => ["test:rubies", "test:javascripts"] -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/TODO.taskpaper: -------------------------------------------------------------------------------- 1 | Release 1: 2 | - cleanup README 3 | - include correct copyright notices of vendored software @done 4 | - add API documentation (require, etc) @done 5 | - explain that we're jQuery-opinionated, but give jQuery.noConflict() example for Prototype @done 6 | - list Java (version?) as a system requirement 7 | - improve test output for command line @done(2009-01-30) 8 | - merge back to Relevance's javascript_testing project on GitHub @done 9 | - change generators to use Screw.Unit style instead of JS-Spec @done 10 | - test that env-js works with DOCTYPEs now? @done(2009-01-30) 11 | - rake task to open fixtures in your favorite web browser? @done 12 | - make the generator check for "test", "spec", and then "examples" directory to create the "javascript" dir @done(2009-04-11) 13 | - support Prototype @done 14 | - support jQuery 1.3.x @env.js @done(2009-05-08) 15 | - in browser @done(2009-04-11) 16 | - from command line @done(2009-05-08) 17 | - when clicking on a describe or it block in browser, run focused tests (thanks rsim!) @done(2009-04-11) 18 | - fix timing issues of "require" calls in browser tests often causing first test to fail @done(2009-04-11) 19 | - include Smoke for mocking @done(2009-04-11) 20 | - automatically require @done(2009-04-11) 21 | - command line @done(2009-04-11) 22 | - browser @done(2009-04-11) 23 | - add examples of mocking to README @done 24 | - improve mocking example in README - show code under test 25 | - caveat re stubbing in README 26 | - change name of plugin @done 27 | - change the relevance github fork's name @done 28 | - create a "javascript_testing" github project with a README that points folks to the new name @done 29 | - what is the new name? --> "blue-ridge" @done 30 | Release 2: 31 | - Document TextMate support 32 | - fork the screw.unit text mate bundle 33 | - add the TextMate runner from the karnowski/javascript_testing Textmate bundle 34 | - "git clone git://github.com/coreyti/screw-unit-tmbundle.git screw-unit.tmbundle" 35 | - have to remove the "run" macro there 36 | - "git clone git://github.com/karnowski/javascript-testing-tmbundle.git javascript-testing.tmbundle" 37 | - needs to be smart enough to look for spec, test, or examples -- right now hard-coded to "test" 38 | - known text-mate issue with builder.rb: http://robsanheim.com/2007/12/07/fixing-textmate-test-issues-blank_slate_method_added-stack-level-too-deep-systemstackerror/ 39 | - might also have to move it in the "Pristine Copy" version too 40 | - sprockets support? 41 | - improve "require" to take an array and chain them together in order 42 | - handle display of nested describes better for command-line 43 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/generators/blue_ridge/blue_ridge_generator.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../../lib/blue_ridge') 2 | 3 | class BlueRidgeGenerator < Rails::Generator::Base 4 | def manifest 5 | record do |m| 6 | base_dir = BlueRidge.javascript_spec_dir 7 | 8 | m.directory base_dir 9 | m.file 'application_spec.js', "#{base_dir}/application_spec.js" 10 | m.file 'spec_helper.js', "#{base_dir}/spec_helper.js" 11 | 12 | m.directory "#{base_dir}/fixtures" 13 | m.file 'application.html', "#{base_dir}/fixtures/application.html" 14 | m.file 'screw.css', "#{base_dir}/fixtures/screw.css" 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/generators/blue_ridge/templates/application.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Application | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 |
    13 | 14 |
    15 | 16 | 17 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/generators/blue_ridge/templates/application_spec.js: -------------------------------------------------------------------------------- 1 | require("spec_helper.js"); 2 | require("../../public/javascripts/application.js"); 3 | 4 | Screw.Unit(function(){ 5 | describe("Your application javascript", function(){ 6 | it("does something", function(){ 7 | expect("hello").to(equal, "hello"); 8 | }); 9 | 10 | it("accesses the DOM from fixtures/application.html", function(){ 11 | expect($('.select_me').length).to(equal, 2); 12 | }); 13 | }); 14 | }); 15 | 16 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/generators/blue_ridge/templates/screw.css: -------------------------------------------------------------------------------- 1 | html { 2 | padding: 0.5em; 3 | font-family: Georgia, serif; 4 | background: #EDEBD5; 5 | } 6 | 7 | li { 8 | list-style-type: none; 9 | } 10 | 11 | .focused { 12 | background-color: #F4F2E4; 13 | } 14 | 15 | .focused * { 16 | opacity: 1.0; 17 | } 18 | 19 | h1, h2, p { 20 | opacity: 0.4; 21 | } 22 | 23 | .describes { 24 | padding-left: 0; 25 | } 26 | 27 | .describes h1 { 28 | font-size: 1.1em; 29 | color: #877C21; 30 | line-height: 1.8em; 31 | margin: 0pt 0pt 0.6em; 32 | border-bottom: 1px solid transparent; 33 | } 34 | 35 | .describes h1:hover { 36 | cursor: pointer; 37 | color: #000; 38 | background-color: #F4F2E4; 39 | border-bottom: 1px solid #9A8E51; 40 | } 41 | 42 | .describes .describe { 43 | margin-left: 0.6em; 44 | padding-left: 0.6em; 45 | border: 1px dashed #999; 46 | } 47 | 48 | .describes .describe .its {} 49 | 50 | .describes .describe .its .it { 51 | list-style-type: lower-roman; 52 | list-style-position: outside; 53 | } 54 | 55 | .describes .describe .its .it h2 { 56 | font-weight: normal; 57 | font-style: italic; 58 | padding-left: 0.5em; 59 | font-size: 1.0em; 60 | color: #877C21; 61 | line-height: 1.8em; 62 | margin: 0 0 0.5em; 63 | border-bottom: 1px solid transparent; 64 | } 65 | 66 | .describes .describe .its .it.enqueued h2 { 67 | background-color: #CC6600; 68 | color: white !important; 69 | } 70 | 71 | .describes .describe .its .it.passed h2 { 72 | background-color: #5A753D; 73 | color: white !important; 74 | } 75 | 76 | .describes .describe .its .it.failed h2 { 77 | background-color: #993300; 78 | color: white !important; 79 | } 80 | 81 | .describes .describe .its .it.failed p { 82 | margin-left: 1em; 83 | color: #993300; 84 | } 85 | 86 | .describes .describe .its .it h2:hover { 87 | cursor: pointer; 88 | color: #000 !important; 89 | border-bottom: 1px solid #9A8E51; 90 | } 91 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/generators/blue_ridge/templates/spec_helper.js: -------------------------------------------------------------------------------- 1 | // Use this file to require common dependencies or to setup useful test functions. -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/generators/javascript_spec/javascript_spec_generator.rb: -------------------------------------------------------------------------------- 1 | class JavascriptSpecGenerator < Rails::Generator::NamedBase 2 | def manifest 3 | file_path_with_spec, file_path_without_spec = file_path_with_and_without_spec 4 | 5 | record do |m| 6 | base_dir = BlueRidge.javascript_spec_dir 7 | 8 | m.directory base_dir 9 | m.directory "#{base_dir}/fixtures" 10 | 11 | options = {:class_name_without_spec => class_name_without_spec, :file_path_without_spec => file_path_without_spec} 12 | m.template 'javascript_spec.js.erb', "#{base_dir}/#{file_path_with_spec}.js", :assigns => options 13 | m.template 'fixture.html.erb', "#{base_dir}/fixtures/#{file_path_without_spec}.html", :assigns => options 14 | end 15 | end 16 | 17 | def file_path_with_and_without_spec 18 | if (file_path =~ /_spec$/i) 19 | [file_path, file_path.gsub(/_spec$/, "")] 20 | else 21 | [file_path + "_spec", file_path] 22 | end 23 | end 24 | 25 | def class_name_without_spec 26 | (class_name =~ /Spec$/) ? class_name.gsub(/Spec$/, "") : class_name 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/generators/javascript_spec/templates/fixture.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%= class_name_without_spec %> | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/generators/javascript_spec/templates/javascript_spec.js.erb: -------------------------------------------------------------------------------- 1 | require("spec_helper.js"); 2 | require("../../public/javascripts/<%= file_path_without_spec %>.js"); 3 | 4 | Screw.Unit(function(){ 5 | describe("<%= class_name_without_spec %>", function(){ 6 | it("does something", function(){ 7 | expect("hello").to(equal, "hello"); 8 | }); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/blue-ridge.js: -------------------------------------------------------------------------------- 1 | var BLUE_RIDGE_LIB_PREFIX = BLUE_RIDGE_LIB_PREFIX || "../../vendor/plugins/blue-ridge/lib/"; 2 | 3 | var BlueRidge = { 4 | require: function(url, callback){ 5 | // add a '../' prefix to all JavaScript paths because we expect to be ran from one of: 6 | // * test/javascript/fixtures 7 | // * specs/javascripts/fixtures 8 | // * examples/javascripts/fixtures 9 | url = "../" + url; 10 | 11 | var head = document.getElementsByTagName("head")[0]; 12 | var script = document.createElement("script"); 13 | script.src = url; 14 | 15 | if(callback){ 16 | var done = false; 17 | // Attach handlers for all browsers 18 | script.onload = script.onreadystatechange = function(){ 19 | if (!done && (!this.readyState || 20 | this.readyState == "loaded" || this.readyState == "complete") ) { 21 | done = true; 22 | callback.call(); 23 | // Handle memory leak in IE 24 | script.onload = script.onreadystatechange = null; 25 | head.removeChild( script ); 26 | } 27 | }; 28 | }; 29 | head.appendChild(script); 30 | }, 31 | 32 | debug: function(message){ 33 | document.writeln(message + "
    "); 34 | }, 35 | 36 | deriveSpecNameFromCurrentFile: function(){ 37 | var file_prefix = new String(window.location).match(/.*\/(.*?)\.html/)[1]; 38 | return file_prefix + "_spec.js"; 39 | } 40 | }; 41 | 42 | var require = require || BlueRidge.require; 43 | var debug = debug || BlueRidge.debug; 44 | 45 | // all required js libs are now nested to load properly 46 | 47 | require(BLUE_RIDGE_LIB_PREFIX + "jquery-1.3.2.js", function(){ 48 | require(BLUE_RIDGE_LIB_PREFIX + "jquery.fn.js", function(){ 49 | require(BLUE_RIDGE_LIB_PREFIX + "jquery.print.js", function(){ 50 | require(BLUE_RIDGE_LIB_PREFIX + "screw.builder.js", function(){ 51 | require(BLUE_RIDGE_LIB_PREFIX + "screw.matchers.js", function(){ 52 | require(BLUE_RIDGE_LIB_PREFIX + "screw.events.js", function(){ 53 | require(BLUE_RIDGE_LIB_PREFIX + "screw.behaviors.js", function(){ 54 | require(BLUE_RIDGE_LIB_PREFIX + "smoke.core.js", function(){ 55 | require(BLUE_RIDGE_LIB_PREFIX + "smoke.mock.js", function(){ 56 | require(BLUE_RIDGE_LIB_PREFIX + "smoke.stub.js", function(){ 57 | require(BLUE_RIDGE_LIB_PREFIX + "screw.mocking.js",function(){ 58 | 59 | require(BLUE_RIDGE_LIB_PREFIX + "smok.js",function(){ 60 | require(BLUE_RIDGE_LIB_PREFIX + "screw.smok.js",function(){ 61 | 62 | require(BlueRidge.deriveSpecNameFromCurrentFile()); 63 | 64 | }); 65 | }); 66 | 67 | }); 68 | }); 69 | }); 70 | }); 71 | }); 72 | }); 73 | }); 74 | }); 75 | }); 76 | }); 77 | }); 78 | 79 | 80 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/blue_ridge.rb: -------------------------------------------------------------------------------- 1 | module BlueRidge 2 | JavaScriptSpecDirs = ["examples/javascripts", "spec/javascripts", "test/javascript"] 3 | 4 | def self.plugin_prefix 5 | ENV["BLUE_RIDGE_PREFIX"] || "#{RAILS_ROOT}/vendor/plugins/blue-ridge" 6 | end 7 | 8 | def self.rhino_command 9 | "java -Dblue.ridge.prefix=\"#{plugin_prefix}\" -jar #{plugin_prefix}/lib/js.jar -w -debug" 10 | end 11 | 12 | def self.test_runner_command 13 | "#{rhino_command} #{plugin_prefix}/lib/test_runner.js" 14 | end 15 | 16 | def self.find_base_spec_dir 17 | return "examples" if File.exist?("examples") 18 | return "spec" if File.exist?("spec") 19 | "test" 20 | end 21 | 22 | def self.javascript_spec_dir 23 | base_spec_dir = find_base_spec_dir 24 | return "test/javascript" if base_spec_dir == "test" 25 | base_spec_dir + "/javascripts" 26 | end 27 | 28 | def self.find_javascript_spec_dir 29 | JavaScriptSpecDirs.find {|d| File.exist?(d) } 30 | end 31 | 32 | def self.find_specs_under_current_dir 33 | Dir.glob("*_spec.js") 34 | end 35 | 36 | def self.run_spec(spec_filename) 37 | system("#{test_runner_command} #{spec_filename}") 38 | end 39 | 40 | def self.run_specs_in_dir(spec_dir, spec_name = nil) 41 | result = nil 42 | Dir.chdir(spec_dir) { result = run_specs(spec_name) } 43 | result 44 | end 45 | 46 | def self.run_specs(spec_name = nil) 47 | specs = spec_name.nil? ? find_specs_under_current_dir : ["#{spec_name}_spec.js"] 48 | all_fine = specs.inject(true) {|result, spec| result &= run_spec(spec) } 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/consoleReportForRake.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | var failedSpecs = [], 3 | ESC = String.fromCharCode(27), 4 | GREEN = ESC + "[32m", 5 | RED = ESC + "[31m", 6 | RESET = ESC + "[0m", 7 | 8 | // change it to false if your text output doesn't support colouring 9 | coloured = true; 10 | 11 | function printGreen(message){ 12 | if(coloured) { message = GREEN + message + RESET; } 13 | print(message); 14 | } 15 | 16 | function printRed(message){ 17 | if(coloured) { message = RED + message + RESET; } 18 | print(message); 19 | } 20 | 21 | $(Screw).bind("before", function(){ 22 | var currentContext = ""; 23 | 24 | function context_name(element){ 25 | var context_name = ""; 26 | $(element).parents(".describe").children("h1").each(function(){ 27 | context_name = $(this).text() + " " + context_name; 28 | }); 29 | return context_name.replace(/^\s+|\s+$/g, ''); 30 | } 31 | 32 | function example_name(element){ 33 | return $(element).children("h2").text(); 34 | } 35 | 36 | function updateContext(context){ 37 | if(context != currentContext){ 38 | currentContext = context; 39 | print("\n" + context); 40 | } 41 | }; 42 | 43 | function report(example, failReason){ 44 | var failed = typeof failReason != 'undefined', 45 | context = context_name(example), 46 | example = example_name(example), 47 | print = failed ? printRed : printGreen, 48 | message = " - " + example; 49 | if (failed) { 50 | message += " (FAILED - " + (failedSpecs.length+1) + ")"; 51 | failedSpecs.push([context, example, failReason]) 52 | } 53 | updateContext(context); 54 | print(message); 55 | } 56 | 57 | $('.it') 58 | .bind('passed', function(){ 59 | report(this); 60 | }) 61 | .bind('failed', function(e, reason){ 62 | report(this, reason); 63 | }); 64 | }); 65 | 66 | $(Screw).bind("after", function(){ 67 | var testCount = $('.passed').length + $('.failed').length; 68 | var failures = $('.failed').length; 69 | var elapsedTime = ((new Date() - Screw.suite_start_time)/1000.0); 70 | 71 | print("\n") 72 | $.each(failedSpecs, function(i, fail){ 73 | printRed((i+1) + ")"); 74 | printRed(fail[0] + " " + fail[1] + " FAILED:") 75 | printRed(" " + fail[2] + "\n"); 76 | }); 77 | print(testCount + ' test(s), ' + failures + ' failure(s)'); 78 | print(elapsedTime.toString() + " seconds elapsed"); 79 | 80 | if(failures > 0) { java.lang.System.exit(1) }; 81 | }); 82 | })(jQuery); 83 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/jquery.fn.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $.fn.fn = function() { 3 | var self = this; 4 | var extension = arguments[0], name = arguments[0]; 5 | if (typeof name == "string") { 6 | return apply(self, name, $.makeArray(arguments).slice(1, arguments.length)); 7 | } else { 8 | $.each(extension, function(key, value) { 9 | define(self, key, value); 10 | }); 11 | return self; 12 | } 13 | } 14 | function define(self, name, fn) { 15 | self.data(namespacedName(name), fn); 16 | }; 17 | function apply(self, name, args) { 18 | var result; 19 | self.each(function(i, item) { 20 | var fn = $(item).data(namespacedName(name)); 21 | if (fn) result = fn.apply(item, args) 22 | else throw(name + " is not defined"); 23 | }); 24 | return result; 25 | }; 26 | function namespacedName(name) { 27 | return 'fn.' + name; 28 | } 29 | })(jQuery); -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/js.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/vendor/plugins/blue-ridge/lib/js.jar -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/screw.behaviors.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $(Screw).bind('loaded', function() { 3 | $('.status').fn({ 4 | display: function() { 5 | $(this).html( 6 | $('.passed').length + $('.failed').length + ' test(s), ' + $('.failed').length + ' failure(s)
    ' + 7 | ((new Date() - Screw.suite_start_time)/1000.0).toString() + " seconds elapsed" 8 | ); 9 | } 10 | }); 11 | 12 | $('.describe').fn({ 13 | parent: function() { 14 | return $(this).parent('.describes').parent('.describe'); 15 | }, 16 | 17 | run_befores: function() { 18 | $(this).fn('parent').fn('run_befores'); 19 | $(this).children('.befores').children('.before').fn('run'); 20 | }, 21 | 22 | run_afters: function() { 23 | $(this).fn('parent').fn('run_afters'); 24 | $(this).children('.afters').children('.after').fn('run'); 25 | }, 26 | 27 | enqueue: function() { 28 | $(this).children('.its').children('.it').fn('enqueue'); 29 | $(this).children('.describes').children('.describe').fn('enqueue'); 30 | }, 31 | 32 | selector: function() { 33 | return $(this).fn('parent').fn('selector') 34 | + ' > .describes > .describe:eq(' + $(this).parent('.describes').children('.describe').index(this) + ')'; 35 | } 36 | }); 37 | 38 | $('body > .describe').fn({ 39 | selector: function() { return 'body > .describe' } 40 | }); 41 | 42 | $('.it').fn({ 43 | parent: function() { 44 | return $(this).parent('.its').parent('.describe'); 45 | }, 46 | 47 | run: function() { 48 | try { 49 | try { 50 | $(this).fn('parent').fn('run_befores'); 51 | $(this).data('screwunit.run')(); 52 | } finally { 53 | $(this).fn('parent').fn('run_afters'); 54 | } 55 | $(this).trigger('passed'); 56 | } catch(e) { 57 | $(this).trigger('failed', [e]); 58 | } 59 | }, 60 | 61 | enqueue: function() { 62 | var self = $(this).trigger('enqueued'); 63 | $(Screw) 64 | .queue(function() { 65 | self.fn('run'); 66 | setTimeout(function() { $(Screw).dequeue() }, 0); 67 | }); 68 | }, 69 | 70 | selector: function() { 71 | return $(this).fn('parent').fn('selector') 72 | + ' > .its > .it:eq(' + $(this).parent('.its').children('.it').index(this) + ')'; 73 | } 74 | }); 75 | 76 | $('.before').fn({ 77 | run: function() { $(this).data('screwunit.run')() } 78 | }); 79 | 80 | $('.after').fn({ 81 | run: function() { $(this).data('screwunit.run')() } 82 | }); 83 | 84 | $(Screw).trigger('before'); 85 | var to_run = unescape(location.search.slice(1)) || 'body > .describe > .describes > .describe'; 86 | $(to_run) 87 | .focus() 88 | .eq(0).trigger('scroll').end() 89 | .fn('enqueue'); 90 | $(Screw).queue(function() { $(Screw).trigger('after') }); 91 | }) 92 | })(jQuery); 93 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/screw.builder.js: -------------------------------------------------------------------------------- 1 | var Screw = (function($) { 2 | var screw = { 3 | Unit: function(fn) { 4 | var contents = fn.toString().match(/^[^\{]*{((.*\n*)*)}/m)[1]; 5 | var fn = new Function("matchers", "specifications", 6 | "with (specifications) { with (matchers) { " + contents + " } }" 7 | ); 8 | 9 | $(Screw).queue(function() { 10 | Screw.Specifications.context.push($('body > .describe')); 11 | fn.call(this, Screw.Matchers, Screw.Specifications); 12 | Screw.Specifications.context.pop(); 13 | $(this).dequeue(); 14 | }); 15 | }, 16 | 17 | Specifications: { 18 | context: [], 19 | 20 | describe: function(name, fn) { 21 | var describe = $('
  • ') 22 | .append($('

    ').text(name)) 23 | .append('
      ') 24 | .append('
        ') 25 | .append('
          ') 26 | .append('
            '); 27 | 28 | this.context.push(describe); 29 | fn.call(); 30 | this.context.pop(); 31 | 32 | this.context[this.context.length-1] 33 | .children('.describes') 34 | .append(describe); 35 | }, 36 | 37 | it: function(name, fn) { 38 | var it = $('
          1. ') 39 | .append($('

            ').text(name)) 40 | .data('screwunit.run', fn); 41 | 42 | this.context[this.context.length-1] 43 | .children('.its') 44 | .append(it); 45 | }, 46 | 47 | before: function(fn) { 48 | var before = $('
          2. ') 49 | .data('screwunit.run', fn); 50 | 51 | this.context[this.context.length-1] 52 | .children('.befores') 53 | .append(before); 54 | }, 55 | 56 | after: function(fn) { 57 | var after = $('
          3. ') 58 | .data('screwunit.run', fn); 59 | 60 | this.context[this.context.length-1] 61 | .children('.afters') 62 | .append(after); 63 | } 64 | } 65 | }; 66 | 67 | $(screw).queue(function() { $(screw).trigger('loading') }); 68 | 69 | $(function() { 70 | $('
            ') 71 | .append('

            ') 72 | .append('
              ') 73 | .append('
                ') 74 | .append('
                  ') 75 | .appendTo('body'); 76 | 77 | $(screw).dequeue(); 78 | $(screw).trigger('loaded'); 79 | }); 80 | 81 | return screw; 82 | })(jQuery); 83 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/screw.events.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $(Screw) 3 | .bind('loaded', function() { 4 | $('.describe, .it') 5 | .click(function() { 6 | document.location = location.href.split('?')[0] + '?' + $(this).fn('selector'); 7 | return false; 8 | }) 9 | .focus(function() { 10 | return $(this).addClass('focused'); 11 | }) 12 | .bind('scroll', function() { 13 | document.body.scrollTop = $(this).offset().top; 14 | }); 15 | 16 | $('.it') 17 | .bind('enqueued', function() { 18 | $(this).addClass('enqueued'); 19 | }) 20 | .bind('running', function() { 21 | $(this).addClass('running'); 22 | }) 23 | .bind('passed', function() { 24 | $(this).addClass('passed'); 25 | }) 26 | .bind('failed', function(e, reason) { 27 | $(this) 28 | .addClass('failed') 29 | .append($('

                  ').text(reason.toString())); 30 | 31 | var file = reason.fileName || reason.sourceURL; 32 | var line = reason.lineNumber || reason.line; 33 | if (file || line) { 34 | $(this).append($('

                  ').text('line ' + line + ', ' + file)); 35 | } 36 | }) 37 | }) 38 | .bind('before', function() { 39 | Screw.suite_start_time = new Date(); 40 | $('.status').text('Running...'); 41 | }) 42 | .bind('after', function() { 43 | $('.status').fn('display') 44 | }) 45 | })(jQuery); -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/screw.mocking.js: -------------------------------------------------------------------------------- 1 | // This is a lightweight bridge between Smoke and Screw.Unit. 2 | // It shadows mocking and stubbing onto the matchers to make them available within tests. 3 | 4 | Screw.Matchers.mock = function(m) { 5 | return Smoke.Mock(m); 6 | }; 7 | 8 | Screw.Matchers.mock_function = function(func,name) { 9 | return Smoke.MockFunction(func,name); 10 | }; 11 | 12 | Screw.Matchers.stub = function(obj, attr) { 13 | return new Smoke.Stub(obj,attr); 14 | }; 15 | 16 | (function($) { 17 | $(Screw).bind("before", function(){ 18 | function checkAndResetSmoke() { 19 | Smoke.checkExpectations(); 20 | Smoke.reset(); 21 | } 22 | 23 | $('.it').bind('passed', function(){ checkAndResetSmoke() }); 24 | $('.it').bind('failed', function(){ checkAndResetSmoke() }); 25 | }); 26 | })(jQuery); 27 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/screw.smok.js: -------------------------------------------------------------------------------- 1 | function checkAndResetSmok() { 2 | if(!Smok.check()) { 3 | Smok.reset(); 4 | throw "Smok Expectation failed!" 5 | } 6 | Smok.reset(); 7 | } 8 | 9 | Screw.Unit(function() { 10 | after(function() { checkAndResetSmok() }); 11 | }); 12 | 13 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/shell.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var _old_quit = this.quit; 3 | this.__defineGetter__("exit", function(){ _old_quit() }); 4 | this.__defineGetter__("quit", function(){ _old_quit() }); 5 | 6 | print("================================================="); 7 | print(" Rhino JavaScript Shell"); 8 | print(" To exit type 'exit', 'quit', or 'quit()'."); 9 | print("================================================="); 10 | 11 | var plugin_prefix = environment["blue.ridge.prefix"] || "vendor/plugins/blue-ridge"; 12 | var fixture_file = plugin_prefix + "/generators/blue_ridge/templates/application.html"; 13 | 14 | load(plugin_prefix + "/lib/env.rhino.js"); 15 | print(" - loaded env.js"); 16 | 17 | window.location = fixture_file; 18 | print(" - sample DOM loaded"); 19 | 20 | load(plugin_prefix + "/lib/jquery-1.3.2.js"); 21 | print(" - jQuery-1.3.2 loaded"); 22 | 23 | load(plugin_prefix + "/lib/jquery.print.js"); 24 | print(" - jQuery print lib loaded"); 25 | 26 | print("================================================="); 27 | })(); 28 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/smoke.core.js: -------------------------------------------------------------------------------- 1 | Smoke = { 2 | print: function(v) { 3 | // use the jquery print plugin if it is available or fall back to toString(); 4 | return (jQuery && jQuery.print) ? jQuery.print(v) : v.toString(); 5 | }, 6 | 7 | printArguments: function(args) { 8 | var a = []; 9 | if (args === undefined) args = ''; 10 | if ((args && args.callee) || (args instanceof Array)) { 11 | for(var i = 0; i < args.length; i++) { 12 | a.push(Smoke.print(args[i])); 13 | } 14 | } else { 15 | // Workaround for jQuery.print returning "null" when called with an empty string. 16 | if (!args && (typeof args == 'string')) { 17 | a.push(''); 18 | } else { 19 | a.push(Smoke.print(args)); 20 | } 21 | } 22 | return '(' + a.join(', ') + ')'; 23 | }, 24 | 25 | argumentsToArray: function(args) { 26 | return Array.prototype.slice.call(args); 27 | }, 28 | 29 | compare: function(a, b) { 30 | if (a === b) return true; 31 | if (a instanceof Array) { 32 | if (b.length != a.length) return false; 33 | for (var i = 0; i < b.length; i++) 34 | if (!this.compare(a[i], b[i])) return false; 35 | } else if (a instanceof Object) { 36 | for (var key in a) 37 | if (!this.compare(a[key], b[key])) return false; 38 | for (var key in b) 39 | if (!this.compare(b[key], a[key])) return false; 40 | } else { 41 | return false; 42 | } 43 | return true; 44 | }, 45 | 46 | compareArguments: function(a, b) { 47 | return this.compare(Smoke.argumentsToArray(a), Smoke.argumentsToArray(b)); 48 | } 49 | }; -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/smoke.stub.js: -------------------------------------------------------------------------------- 1 | Smoke.Stub = function(obj,attr) { 2 | this.obj = obj; 3 | this.attribute = attr; 4 | this.and_return(this.defaultReturn); 5 | }; 6 | 7 | Smoke.Stub.prototype = { 8 | defaultReturn: null, 9 | property: function(p){ 10 | this.property = p; 11 | this.and_set_to(this.defaultReturn); 12 | return this 13 | }, 14 | method: function(f){ 15 | this.func = f; 16 | this.and_return(this.defaultReturn); 17 | return this 18 | }, 19 | and_return: function(v){ 20 | this.obj[this.attribute] = function() { 21 | return v 22 | }; 23 | return this.obj 24 | }, 25 | and_set_to: function(v){ 26 | this.obj[this.attribute] = v; 27 | return this.obj 28 | } 29 | }; -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/lib/test_runner.js: -------------------------------------------------------------------------------- 1 | if(arguments.length == 0) { 2 | print("Usage: test_runner.js spec/javascripts/file_spec.js"); 3 | quit(1); 4 | } 5 | 6 | var PLUGIN_PREFIX = environment["blue.ridge.prefix"] || "../../vendor/plugins/blue-ridge"; 7 | 8 | var BlueRidge = { 9 | require: function(file, callback){ 10 | load(file); 11 | 12 | if(callback) { 13 | callback.call(); 14 | } 15 | }, 16 | 17 | debug: function(message){ 18 | print(message); 19 | }, 20 | 21 | get fixtureFile(){ 22 | return "fixtures/" + this.specFile.replace(/^(.*?)_spec\.js$/, "$1.html"); 23 | } 24 | }; 25 | 26 | BlueRidge.specFile = arguments[0]; 27 | 28 | var require = require || BlueRidge.require; 29 | var debug = debug || BlueRidge.debug; 30 | 31 | // Mock up the Firebug API for convenience. 32 | var console = console || {debug: debug}; 33 | 34 | load(PLUGIN_PREFIX + "/lib/env.rhino.js"); 35 | window.location = BlueRidge.fixtureFile; 36 | 37 | load(PLUGIN_PREFIX + "/lib/jquery-1.3.2.js"); 38 | load(PLUGIN_PREFIX + "/lib/jquery.fn.js"); 39 | load(PLUGIN_PREFIX + "/lib/jquery.print.js"); 40 | load(PLUGIN_PREFIX + "/lib/screw.builder.js"); 41 | load(PLUGIN_PREFIX + "/lib/screw.matchers.js"); 42 | load(PLUGIN_PREFIX + "/lib/screw.events.js"); 43 | load(PLUGIN_PREFIX + "/lib/screw.behaviors.js"); 44 | load(PLUGIN_PREFIX + "/lib/smoke.core.js"); 45 | load(PLUGIN_PREFIX + "/lib/smoke.mock.js"); 46 | load(PLUGIN_PREFIX + "/lib/smoke.stub.js"); 47 | load(PLUGIN_PREFIX + "/lib/screw.mocking.js"); 48 | load(PLUGIN_PREFIX + "/lib/smok.js"); 49 | load(PLUGIN_PREFIX + "/lib/screw.smok.js"); 50 | load(PLUGIN_PREFIX + "/lib/consoleReportForRake.js"); 51 | 52 | print("Running " + BlueRidge.specFile + " with fixture '" + BlueRidge.fixtureFile + "'..."); 53 | load(BlueRidge.specFile); 54 | jQuery(window).trigger("load"); 55 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/fixtures/screw.behaviors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Screw.Unit Behaviors | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/fixtures/screw.matchers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Screw.Unit Matchers | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/fixtures/screw.print.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Screw.Unit Print | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/fixtures/smoke.core.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Smoke Core | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/fixtures/smoke.mock.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Smoke Mocking | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/fixtures/smoke.screw_integration.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Smoke Stubbing | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/fixtures/smoke.stub.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Smoke Stubbing | JavaScript Testing Results 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/smoke.screw_integration_spec.js: -------------------------------------------------------------------------------- 1 | Screw.Unit(function() { 2 | describe("integrating with Screw.Unit", function() { 3 | before(function() { 4 | foo = {bar: function(attribute){return 'hello'}, baz:'goodbye'}; 5 | }); 6 | 7 | it("should forward stub() calls to new Stub to allow stub().and_return()", function() { 8 | var myStub = stub(foo,'baz') 9 | expect(myStub.and_return).to_not(equal, undefined); 10 | }); 11 | 12 | it("should forward mock() calls to new mock object to allow mock().should_receive()", function() { 13 | var myMock = mock(foo); 14 | expect(myMock.should_receive).to_not(equal,undefined) 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/smoke.stub_spec.js: -------------------------------------------------------------------------------- 1 | Screw.Unit(function() { 2 | describe("stubbing", function() { 3 | before(function() { 4 | foo = {bar: function(attribute){return 'hello'}, baz:'goodbye'}; 5 | }); 6 | 7 | it("should return the stubbed value of a property", function() { 8 | stub(foo,'baz').and_set_to('baz'); 9 | expect(foo.baz).to(equal, 'baz'); 10 | }); 11 | 12 | it("should return the stubbed value of a function", function() { 13 | stub(foo,'bar').and_return('bar'); 14 | expect(foo.bar()).to(equal, 'bar'); 15 | }); 16 | }); 17 | }); -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/javascripts/spec_helper.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/vendor/plugins/blue-ridge/spec/javascripts/spec_helper.js -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/spec/rubies/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require "micronaut" 2 | 3 | def not_in_editor? 4 | ['TM_MODE', 'EMACS', 'VIM'].all? { |k| !ENV.has_key?(k) } 5 | end 6 | 7 | Micronaut.configure do |config| 8 | config.formatter = :progress 9 | config.mock_with :mocha 10 | config.color_enabled = not_in_editor? 11 | config.filter_run :focused => true 12 | config.alias_example_to :fit, :focused => true 13 | config.profile_examples = false 14 | end 15 | -------------------------------------------------------------------------------- /vendor/plugins/blue-ridge/tasks/javascript_testing_tasks.rake: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../lib/blue_ridge') 2 | 3 | def error_message_for_missing_spec_dir 4 | %Q{Could not find JavaScript test directory. 5 | None of the following directories existed: #{BlueRidge::JavaScriptSpecDirs.join(", ")}. 6 | Maybe you need to call './script/generate blue_ridge'? 7 | } 8 | end 9 | 10 | # Support Test::Unit & Test/Spec style 11 | namespace :test do 12 | desc "Runs all the JavaScript tests and outputs the results" 13 | task :javascripts do 14 | js_spec_dir = BlueRidge.find_javascript_spec_dir || (raise error_message_for_missing_spec_dir) 15 | raise "JavaScript test failures" unless BlueRidge.run_specs_in_dir(js_spec_dir, ENV["TEST"]) 16 | end 17 | 18 | task :javascript => :javascripts 19 | end 20 | 21 | # Support RSpec style 22 | namespace :spec do 23 | task :javascripts => "test:javascripts" 24 | task :javascript => "test:javascripts" 25 | end 26 | 27 | # Support Micronaut style 28 | namespace :examples do 29 | task :javascripts => "test:javascripts" 30 | task :javascript => "test:javascripts" 31 | end 32 | 33 | 34 | namespace :js do 35 | task :fixtures do 36 | js_spec_dir = BlueRidge.find_javascript_spec_dir || (raise error_message_for_missing_spec_dir) 37 | fixture_dir = "#{js_spec_dir}/fixtures" 38 | 39 | if PLATFORM[/darwin/] 40 | system("open #{fixture_dir}") 41 | elsif PLATFORM[/linux/] 42 | system("firefox #{fixture_dir}") 43 | else 44 | puts "You can run your in-browser fixtures from #{fixture_dir}." 45 | end 46 | end 47 | 48 | task :shell do 49 | rlwrap = `which rlwrap`.chomp 50 | system("#{rlwrap} #{BlueRidge.rhino_command} -f #{BlueRidge.plugin_prefix}/lib/shell.js -f -") 51 | end 52 | end -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2005 Alexander MacCaw 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/init.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/lib/juggernaut' 2 | require File.dirname(__FILE__) + '/lib/juggernaut_helper' 3 | 4 | ActionView::Base.send(:include, Juggernaut::JuggernautHelper) 5 | 6 | ActionView::Helpers::AssetTagHelper.register_javascript_expansion :juggernaut => ['juggernaut/swfobject', 'juggernaut/juggernaut'] 7 | 8 | ActionController::Base.class_eval do 9 | alias_method :render_without_juggernaut, :render 10 | include Juggernaut::RenderExtension 11 | alias_method :render, :render_with_juggernaut 12 | end 13 | 14 | ActionView::Base.class_eval do 15 | alias_method :render_without_juggernaut, :render 16 | include Juggernaut::RenderExtension 17 | alias_method :render, :render_with_juggernaut 18 | end -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/install.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | 3 | here = File.dirname(__FILE__) 4 | there = defined?(RAILS_ROOT) ? RAILS_ROOT : "#{here}/../../.." 5 | 6 | FileUtils.mkdir_p("#{there}/public/javascripts/juggernaut/") 7 | FileUtils.mkdir_p("#{there}/public/juggernaut/") 8 | 9 | puts "Installing Juggernaut..." 10 | FileUtils.cp("#{here}/media/swfobject.js", "#{there}/public/javascripts/juggernaut/") 11 | FileUtils.cp("#{here}/media/juggernaut.js", "#{there}/public/javascripts/juggernaut/") 12 | FileUtils.cp("#{here}/media/juggernaut.swf", "#{there}/public/juggernaut/") 13 | FileUtils.cp("#{here}/media/expressinstall.swf", "#{there}/public/juggernaut/") 14 | 15 | FileUtils.cp("#{here}/media/juggernaut_hosts.yml", "#{there}/config/") unless File.exist?("#{there}/config/juggernaut_hosts.yml") 16 | puts "Juggernaut has been successfully installed." 17 | puts 18 | puts "Please refer to the readme file #{File.expand_path(here)}/README" -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/lib/juggernaut_helper.rb: -------------------------------------------------------------------------------- 1 | module Juggernaut # :nodoc: 2 | module JuggernautHelper 3 | 4 | def juggernaut(options = {}) 5 | hosts = Juggernaut::CONFIG[:hosts].select {|h| !h[:environment] or h[:environment] == ENV['RAILS_ENV'].to_sym } 6 | random_host = hosts[rand(hosts.length)] 7 | options = { 8 | :host => (random_host[:public_host] || random_host[:host]), 9 | :port => (random_host[:public_port] || random_host[:port]), 10 | :width => '0px', 11 | :height => '0px', 12 | :session_id => request.session_options[:id], 13 | :swf_address => "/juggernaut/juggernaut.swf", 14 | :ei_swf_address => "/juggernaut/expressinstall.swf", 15 | :flash_version => 8, 16 | :flash_color => "#fff", 17 | :swf_name => "juggernaut_flash", 18 | :bridge_name => "juggernaut", 19 | :debug => (RAILS_ENV == 'development'), 20 | :reconnect_attempts => 3, 21 | :reconnect_intervals => 3 22 | }.merge(options) 23 | javascript_tag "new Juggernaut(#{options.to_json});" 24 | end 25 | 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/media/expressinstall.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/vendor/plugins/juggernaut_plugin/media/expressinstall.swf -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/media/jquerynaut.js: -------------------------------------------------------------------------------- 1 | // Simply overwrites prototype specific functions 2 | // with jquery specific versions 3 | 4 | Juggernaut.fn.fire_event = function(fx_name) { 5 | $(document).trigger("juggernaut:" + fx_name); 6 | }; 7 | 8 | Juggernaut.fn.bindToWindow = function() { 9 | $(window).bind("load", this, function(e) { 10 | juggernaut = e.data; 11 | e.data.appendFlashObject(); 12 | }); 13 | }; 14 | 15 | Juggernaut.toJSON = function(hash) { 16 | return $.toJSON(hash) ; 17 | }; 18 | 19 | Juggernaut.parseJSON = function(string) { 20 | return $.parseJSON(string); 21 | }; 22 | 23 | Juggernaut.fn.swf = function(){ 24 | return $('#' + this.options.swf_name)[0]; 25 | }; 26 | 27 | Juggernaut.fn.appendElement = function() { 28 | this.element = $('
                  '); 29 | $("body").append(this.element); 30 | }; 31 | 32 | Juggernaut.fn.refreshFlashObject = function(){ 33 | $(this.swf()).remove(); 34 | this.appendFlashObject(); 35 | }; 36 | 37 | Juggernaut.fn.reconnect = function(){ 38 | if(this.options.reconnect_attempts){ 39 | this.attempting_to_reconnect = true; 40 | this.fire_event('reconnect'); 41 | this.logger('Will attempt to reconnect ' + this.options.reconnect_attempts + ' times, the first in ' + (this.options.reconnect_intervals || 3) + ' seconds'); 42 | var self = this; 43 | for(var i=0; i < this.options.reconnect_attempts; i++){ 44 | setTimeout(function(){ 45 | if(!self.is_connected){ 46 | self.logger('Attempting reconnect'); 47 | if(!self.ever_been_connected){ 48 | self.refreshFlashObject(); 49 | } else { 50 | self.connect(); 51 | } 52 | } 53 | }, (this.options.reconnect_intervals || 3) * 1000 * (i + 1)); 54 | 55 | } 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/media/json.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | var m = { 3 | '\b': '\\b', 4 | '\t': '\\t', 5 | '\n': '\\n', 6 | '\f': '\\f', 7 | '\r': '\\r', 8 | '"' : '\\"', 9 | '\\': '\\\\' 10 | }, 11 | s = { 12 | 'array': function (x) { 13 | var a = ['['], b, f, i, l = x.length, v; 14 | for (i = 0; i < l; i += 1) { 15 | v = x[i]; 16 | f = s[typeof v]; 17 | if (f) { 18 | v = f(v); 19 | if (typeof v == 'string') { 20 | if (b) { 21 | a[a.length] = ','; 22 | } 23 | a[a.length] = v; 24 | b = true; 25 | } 26 | } 27 | } 28 | a[a.length] = ']'; 29 | return a.join(''); 30 | }, 31 | 'boolean': function (x) { 32 | return String(x); 33 | }, 34 | 'null': function (x) { 35 | return "null"; 36 | }, 37 | 'number': function (x) { 38 | return isFinite(x) ? String(x) : 'null'; 39 | }, 40 | 'object': function (x) { 41 | if (x) { 42 | if (x instanceof Array) { 43 | return s.array(x); 44 | } 45 | var a = ['{'], b, f, i, v; 46 | for (i in x) { 47 | v = x[i]; 48 | f = s[typeof v]; 49 | if (f) { 50 | v = f(v); 51 | if (typeof v == 'string') { 52 | if (b) { 53 | a[a.length] = ','; 54 | } 55 | a.push(s.string(i), ':', v); 56 | b = true; 57 | } 58 | } 59 | } 60 | a[a.length] = '}'; 61 | return a.join(''); 62 | } 63 | return 'null'; 64 | }, 65 | 'string': function (x) { 66 | if (/["\\\x00-\x1f]/.test(x)) { 67 | x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) { 68 | var c = m[b]; 69 | if (c) { 70 | return c; 71 | } 72 | c = b.charCodeAt(); 73 | return '\\u00' + 74 | Math.floor(c / 16).toString(16) + 75 | (c % 16).toString(16); 76 | }); 77 | } 78 | return '"' + x + '"'; 79 | } 80 | }; 81 | 82 | $.toJSON = function(v) { 83 | var f = isNaN(v) ? s[typeof v] : s['number']; 84 | if (f) return f(v); 85 | }; 86 | 87 | $.parseJSON = function(v, safe) { 88 | if (safe === undefined) safe = $.parseJSON.safe; 89 | if (safe && !/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(v)) 90 | return undefined; 91 | return eval('('+v+')'); 92 | }; 93 | 94 | $.parseJSON.safe = false; 95 | 96 | })(jQuery); 97 | 98 | -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/media/juggernaut.as: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2007 Alexander MacCaw 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | /* 25 | Compile using MTACS (http://www.mtasc.org/) 26 | mtasc -version 8 -header 1:1:1 -main -swf juggernaut.swf juggernaut.as 27 | */ 28 | 29 | import flash.external.ExternalInterface; 30 | 31 | class SocketServer { 32 | 33 | static var socket : XMLSocket; 34 | 35 | static function connect(host:String, port:Number) { 36 | // The following line was causing crashes on Leopard 37 | // System.security.loadPolicyFile('xmlsocket://' + host + ':' + port); 38 | 39 | socket = new XMLSocket(); 40 | socket.onData = onData; 41 | socket.onConnect = onConnect; 42 | socket.onClose = onDisconnect; 43 | socket.connect(host, port); 44 | } 45 | 46 | static function disconnect(){ 47 | socket.close(); 48 | } 49 | 50 | static function onConnect(success:Boolean) { 51 | if(success){ 52 | ExternalInterface.call("juggernaut.connected"); 53 | } else { 54 | ExternalInterface.call("juggernaut.errorConnecting"); 55 | } 56 | } 57 | 58 | static function sendData(data:String){ 59 | socket.send(unescape(data)); 60 | } 61 | 62 | static function onDisconnect() { 63 | ExternalInterface.call("juggernaut.disconnected"); 64 | } 65 | 66 | static function onData(data:String) { 67 | ExternalInterface.call("juggernaut.receiveData", escape(data)); 68 | } 69 | 70 | static function main() { 71 | ExternalInterface.addCallback("connect", null, connect); 72 | ExternalInterface.addCallback("sendData", null, sendData); 73 | ExternalInterface.addCallback("disconnect", null, disconnect); 74 | 75 | ExternalInterface.call("juggernaut.initialized"); 76 | } 77 | 78 | } 79 | 80 | -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/media/juggernaut.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/vendor/plugins/juggernaut_plugin/media/juggernaut.swf -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/media/juggernaut_hosts.yml: -------------------------------------------------------------------------------- 1 | # You should list any juggernaut hosts here. 2 | # You need only specify the secret key if you're using that type of authentication (see juggernaut.yml) 3 | # 4 | # Name: Mapping: 5 | # :port internal push server's port 6 | # :host internal push server's host/ip 7 | # :public_host public push server's host/ip (accessible from external clients) 8 | # :public_port public push server's port 9 | # :secret_key (optional) shared secret (should map to the key specified in the push server's config) 10 | # :environment (optional) limit host to a particular RAILS_ENV 11 | 12 | :hosts: 13 | - :port: 5001 14 | :host: 127.0.0.1 15 | :public_host: 127.0.0.1 16 | :public_port: 5001 17 | # :secret_key: your_secret_key 18 | # :environment: :development -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/media/log/juggernaut.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WTTechLabs/taskboard/a5eab7fca0a3f80267e7c7637a59ea977daf78c0/vendor/plugins/juggernaut_plugin/media/log/juggernaut.log -------------------------------------------------------------------------------- /vendor/plugins/juggernaut_plugin/tasks/juggernaut.rake: -------------------------------------------------------------------------------- 1 | namespace :juggernaut do 2 | desc "Reinstall the Juggernaut js and swf files" 3 | task :reinstall do 4 | load "#{File.dirname(__FILE__)}/../install.rb" 5 | end 6 | end 7 | 8 | namespace :juggernaut do 9 | desc 'Compile the juggernaut flash file' 10 | task :compile_flash do 11 | `mtasc -version 8 -header 1:1:1 -main -swf media/juggernaut.swf media/juggernaut.as` 12 | end 13 | end 14 | --------------------------------------------------------------------------------