From 93efff945215a4407afcaf0cba15ac601b56df0d Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Sun, 9 Oct 2011 00:34:49 +0300 Subject: [PATCH 001/176] gitignore --- .gitignore | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c83fcb68 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.bundle +.rbx/ +db/*.sqlite3 +log/*.log +tmp/ +.sass-cache/ +coverage/* +*.swp +public/uploads/ From 9ba1224867665844b117fa037e1465bb706b3685 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Sun, 9 Oct 2011 00:36:38 +0300 Subject: [PATCH 002/176] init commit --- .rails_footnotes | 3 + .rspec | 1 + .rvmrc | 1 + CHANGELOG | 14 + Gemfile | 50 ++ Gemfile.lock | 266 ++++++ LICENSE | 19 + README.rdoc | 21 + Rakefile | 7 + VERSION | 1 + app/assets/images/.directory | 4 + app/assets/images/ajax-loader.gif | Bin 0 -> 6820 bytes app/assets/images/blueprint_add.png | Bin 0 -> 4544 bytes app/assets/images/blueprint_delete.png | Bin 0 -> 4506 bytes app/assets/images/blueprint_info.png | Bin 0 -> 4512 bytes app/assets/images/blueprint_notice.png | Bin 0 -> 4531 bytes app/assets/images/dir.png | Bin 0 -> 485 bytes app/assets/images/favicon.ico | Bin 0 -> 1150 bytes app/assets/images/favicon.png | Bin 0 -> 338 bytes app/assets/images/git.png | Bin 0 -> 21559 bytes .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 119 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 5355 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes app/assets/images/no_avatar.png | Bin 0 -> 1335 bytes app/assets/images/rails.png | Bin 0 -> 6646 bytes app/assets/images/txt.png | Bin 0 -> 290 bytes app/assets/javascripts/application.js | 18 + app/assets/javascripts/commits.js | 9 + app/assets/javascripts/dashboard.js.coffee | 3 + app/assets/javascripts/issues.js.coffee | 3 + .../jquery-ui-1.8.16.custom.min.js | 791 ++++++++++++++++ .../javascripts/jquery.ui.selectmenu.js | 845 ++++++++++++++++++ app/assets/javascripts/profile.js.coffee | 3 + app/assets/javascripts/projects.js | 41 + app/assets/stylesheets/application.css | 7 + app/assets/stylesheets/dashboard.css.scss | 3 + app/assets/stylesheets/highlight.css.scss | 135 +++ app/assets/stylesheets/issues.css.scss | 3 + .../stylesheets/jquery.ui.selectmenu.css | 33 + app/assets/stylesheets/profile.css.scss | 3 + app/assets/stylesheets/projects.css.scss | 523 +++++++++++ app/controllers/admin/mailer_controller.rb | 44 + app/controllers/admin/projects_controller.rb | 73 ++ .../admin/team_members_controller.rb | 75 ++ app/controllers/admin/users_controller.rb | 84 ++ app/controllers/application_controller.rb | 40 + app/controllers/commits_controller.rb | 44 + app/controllers/dashboard_controller.rb | 2 + app/controllers/issues_controller.rb | 72 ++ app/controllers/keys_controller.rb | 38 + app/controllers/notes_controller.rb | 49 + app/controllers/profile_controller.rb | 21 + app/controllers/projects_controller.rb | 149 +++ app/controllers/team_members_controller.rb | 66 ++ app/helpers/admin/projects_helper.rb | 2 + app/helpers/admin/users_helper.rb | 2 + app/helpers/application_helper.rb | 77 ++ app/helpers/commits_helper.rb | 24 + app/helpers/dashboard_helper.rb | 2 + app/helpers/issues_helper.rb | 2 + app/helpers/keys_helper.rb | 2 + app/helpers/profile_helper.rb | 2 + app/helpers/projects_helper.rb | 2 + app/helpers/team_members_helper.rb | 2 + app/mailers/.gitkeep | 0 app/mailers/notify.rb | 41 + app/models/.gitkeep | 0 app/models/ability.rb | 34 + app/models/issue.rb | 39 + app/models/key.rb | 58 ++ app/models/note.rb | 41 + app/models/project.rb | 149 +++ app/models/user.rb | 52 ++ app/models/users_project.rb | 35 + app/uploaders/attachment_uploader.rb | 49 + app/views/admin/_top_menu.html.haml | 6 + app/views/admin/mailer/preview.html.haml | 29 + app/views/admin/projects/_form.html.haml | 30 + app/views/admin/projects/edit.html.haml | 5 + app/views/admin/projects/index.html.haml | 26 + app/views/admin/projects/new.html.haml | 5 + app/views/admin/projects/show.html.haml | 45 + app/views/admin/team_members/_form.html.haml | 34 + app/views/admin/team_members/edit.html.haml | 5 + app/views/admin/team_members/index.html.haml | 30 + app/views/admin/team_members/new.html.haml | 5 + app/views/admin/team_members/show.html.haml | 32 + app/views/admin/users/_form.html.haml | 38 + app/views/admin/users/edit.html.haml | 4 + app/views/admin/users/index.html.haml | 24 + app/views/admin/users/new.html.haml | 6 + app/views/admin/users/show.html.haml | 42 + app/views/commits/_commits.html.haml | 22 + app/views/commits/_diff.html.haml | 58 ++ app/views/commits/_index.html.haml | 9 + app/views/commits/index.html.haml | 13 + app/views/commits/index.js.erb | 2 + app/views/commits/show.html.haml | 39 + app/views/commits/show.js.haml | 6 + app/views/dashboard/index.html.haml | 0 app/views/devise/confirmations/new.html.erb | 12 + .../mailer/confirmation_instructions.html.erb | 5 + .../reset_password_instructions.html.erb | 8 + .../mailer/unlock_instructions.html.erb | 7 + app/views/devise/passwords/edit.html.erb | 16 + app/views/devise/passwords/new.html.erb | 15 + app/views/devise/registrations/edit.html.erb | 28 + app/views/devise/registrations/new.html.erb | 18 + app/views/devise/sessions/new.html.erb | 20 + app/views/devise/shared/_links.erb | 25 + app/views/devise/unlocks/new.html.erb | 12 + app/views/issues/_form.html.haml | 24 + app/views/issues/_issues.html.haml | 10 + app/views/issues/_show.html.haml | 18 + app/views/issues/create.js.haml | 9 + app/views/issues/edit.js.haml | 12 + app/views/issues/index.html.haml | 24 + app/views/issues/index.js.haml | 2 + app/views/issues/new.js.haml | 12 + app/views/issues/show.html.haml | 44 + app/views/issues/update.js.haml | 14 + app/views/keys/_form.html.haml | 16 + app/views/keys/_show.html.haml | 4 + app/views/keys/create.js.haml | 8 + app/views/keys/edit.html.haml | 7 + app/views/keys/index.html.haml | 15 + app/views/keys/new.html.haml | 5 + app/views/keys/new.js.haml | 11 + app/views/layouts/_flash.html.haml | 18 + app/views/layouts/_head_panel.html.erb | 34 + app/views/layouts/application.html.haml | 28 + app/views/layouts/notify.html.haml | 36 + app/views/notes/_form.html.haml | 28 + app/views/notes/_notes.html.haml | 14 + app/views/notes/_show.html.haml | 19 + app/views/notes/create.js.haml | 8 + app/views/notify/new_issue_email.html.haml | 18 + app/views/notify/new_user_email.html.haml | 23 + app/views/notify/note_commit_email.html.haml | 23 + app/views/notify/note_issue_email.html.haml | 25 + app/views/notify/note_wall_email.html.haml | 22 + app/views/profile/_top_menu.html.haml | 5 + app/views/profile/index.html.haml | 1 + app/views/profile/password.html.haml | 20 + app/views/profile/show.html.haml | 8 + app/views/projects/_form.html.haml | 50 ++ app/views/projects/_side_panel.html.haml | 14 + app/views/projects/_team.html.haml | 18 + app/views/projects/_top_menu.html.haml | 24 + app/views/projects/_tree.html.haml | 60 ++ app/views/projects/_tree_file.html.haml | 21 + app/views/projects/_tree_item.html.haml | 15 + app/views/projects/create.js.haml | 6 + app/views/projects/edit.html.erb | 1 + app/views/projects/empty.html.erb | 49 + app/views/projects/index.html.haml | 25 + app/views/projects/new.html.erb | 1 + app/views/projects/show.html.haml | 3 + app/views/projects/team.html.haml | 3 + app/views/projects/tree.html.erb | 5 + app/views/projects/tree.js.haml | 5 + app/views/projects/update.js.haml | 6 + app/views/projects/wall.html.haml | 1 + app/views/team_members/_form.html.haml | 25 + app/views/team_members/_show.html.haml | 18 + app/views/team_members/create.js.haml | 9 + app/views/team_members/new.js.haml | 15 + app/views/team_members/update.js.haml | 6 + config.ru | 4 + config/application.rb | 48 + config/boot.rb | 6 + config/database.yml | 25 + config/environment.rb | 7 + config/environments/development.rb | 32 + config/environments/production.rb | 70 ++ config/environments/test.rb | 42 + config/gitosis.yml | 4 + config/initializers/backtrace_silencers.rb | 7 + config/initializers/devise.rb | 211 +++++ config/initializers/inflections.rb | 10 + config/initializers/load_config.rb | 1 + config/initializers/mime_types.rb | 5 + config/initializers/rails_footnotes.rb | 5 + config/initializers/secret_token.rb | 7 + config/initializers/session_store.rb | 8 + config/initializers/wrap_parameters.rb | 14 + config/locales/devise.en.yml | 58 ++ config/locales/en.yml | 10 + config/routes.rb | 46 + configure.rb | 5 + db/fixtures/development/001_admin.rb | 10 + db/fixtures/production/001_admin.rb | 9 + db/fixtures/test/001_repo.rb | 8 + .../20110913200833_devise_create_users.rb | 28 + db/migrate/20110913204141_create_projects.rb | 11 + .../20110914221600_create_users_projects.rb | 13 + ...10915205627_add_private_flag_to_project.rb | 5 + db/migrate/20110915213352_create_keys.rb | 9 + db/migrate/20110916123731_add_name_to_user.rb | 5 + .../20110916162511_add_key_title_to_key.rb | 7 + .../20110917212932_add_identifier_to_key.rb | 5 + db/migrate/20110921192501_create_issues.rb | 13 + .../20110922110156_add_code_to_project.rb | 5 + .../20110923211333_add_status_to_issue.rb | 5 + ...4549_create_rails_admin_histories_table.rb | 18 + .../20110924215658_add_admin_field_to_user.rb | 5 + db/migrate/20110926082616_remove_admin.rb | 9 + db/migrate/20110927130352_create_notes.rb | 12 + .../20110928140106_add_project_id_for_note.rb | 9 + ...10928142747_change_noteable_id_for_note.rb | 9 + .../20110928161328_add_attachment_to_note.rb | 5 + ...193700_add_allow_repo_creation_for_user.rb | 9 + db/pkey.example | 3 + db/schema.rb | 88 ++ db/seeds.rb | 0 doc/README_FOR_APP | 2 + install/prepare.rb | 51 ++ lib/assets/.gitkeep | 0 lib/file_size_validator.rb | 65 ++ lib/gitosis.rb | 70 ++ lib/tasks/.gitkeep | 0 lib/utils.rb | 8 + log/.gitkeep | 0 public/404.html | 25 + public/422.html | 25 + public/500.html | 25 + public/favicon.ico | 0 public/index.html.example | 241 +++++ public/robots.txt | 5 + script/rails | 6 + spec/factories.rb | 43 + spec/factory.rb | 29 + spec/models/issue_spec.rb | 42 + spec/models/key_spec.rb | 32 + spec/models/note_spec.rb | 78 ++ spec/models/project_security_spec.rb | 57 ++ spec/models/project_spec.rb | 126 +++ spec/models/user_spec.rb | 42 + spec/models/users_project_spec.rb | 32 + spec/monkeypatch.rb | 31 + spec/requests/admin/admin_projects_spec.rb | 106 +++ spec/requests/admin/admin_users_spec.rb | 102 +++ spec/requests/admin/security_spec.rb | 27 + spec/requests/commits_notes_spec.rb | 24 + spec/requests/commits_spec.rb | 39 + spec/requests/issues_notes_spec.rb | 27 + spec/requests/issues_spec.rb | 147 +++ spec/requests/keys_spec.rb | 54 ++ spec/requests/profile_spec.rb | 55 ++ spec/requests/projects_security_spec.rb | 111 +++ spec/requests/projects_spec.rb | 152 ++++ spec/requests/projects_tree_spec.rb | 92 ++ spec/requests/projects_wall_spec.rb | 33 + spec/requests/team_members_spec.rb | 46 + spec/requests/top_panel_spec.rb | 34 + spec/requests/user_security_spec.rb | 37 + spec/seed_project.tar.gz | Bin 0 -> 1699843 bytes spec/spec_helper.rb | 56 ++ spec/support/js_patch.rb | 6 + spec/support/login.rb | 29 + spec/support/matchers.rb | 46 + spec/support/security.rb | 0 spec/support/shared_examples.rb | 18 + spec/support/valid_commit.rb | 25 + vendor/assets/stylesheets/.gitkeep | 0 vendor/assets/stylesheets/blueprint/ie.css | 36 + .../blueprint/plugins/buttons/icons/cross.png | Bin 0 -> 655 bytes .../blueprint/plugins/buttons/icons/key.png | Bin 0 -> 455 bytes .../blueprint/plugins/buttons/icons/tick.png | Bin 0 -> 537 bytes .../blueprint/plugins/buttons/readme.txt | 32 + .../blueprint/plugins/buttons/screen.css | 97 ++ .../blueprint/plugins/fancy-type/readme.txt | 14 + .../blueprint/plugins/fancy-type/screen.css | 71 ++ .../plugins/link-icons/icons/doc.png | Bin 0 -> 777 bytes .../plugins/link-icons/icons/email.png | Bin 0 -> 641 bytes .../plugins/link-icons/icons/external.png | Bin 0 -> 46848 bytes .../plugins/link-icons/icons/feed.png | Bin 0 -> 691 bytes .../blueprint/plugins/link-icons/icons/im.png | Bin 0 -> 741 bytes .../plugins/link-icons/icons/lock.png | Bin 0 -> 749 bytes .../plugins/link-icons/icons/pdf.png | Bin 0 -> 591 bytes .../plugins/link-icons/icons/visited.png | Bin 0 -> 46990 bytes .../plugins/link-icons/icons/xls.png | Bin 0 -> 663 bytes .../blueprint/plugins/link-icons/readme.txt | 18 + .../blueprint/plugins/link-icons/screen.css | 42 + .../blueprint/plugins/rtl/readme.txt | 10 + .../blueprint/plugins/rtl/screen.css | 110 +++ vendor/assets/stylesheets/blueprint/print.css | 29 + .../assets/stylesheets/blueprint/screen.css | 265 ++++++ .../stylesheets/blueprint/src/forms.css | 82 ++ .../assets/stylesheets/blueprint/src/grid.css | 280 ++++++ .../assets/stylesheets/blueprint/src/grid.png | Bin 0 -> 195 bytes .../assets/stylesheets/blueprint/src/ie.css | 79 ++ .../stylesheets/blueprint/src/print.css | 92 ++ .../stylesheets/blueprint/src/reset.css | 65 ++ .../stylesheets/blueprint/src/typography.css | 123 +++ .../jquery_ui/jquery-ui-1.8.16.custom.css | 577 ++++++++++++ vendor/plugins/.gitkeep | 0 307 files changed, 11053 insertions(+) create mode 100644 .rails_footnotes create mode 100644 .rspec create mode 100644 .rvmrc create mode 100644 CHANGELOG create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 LICENSE create mode 100644 README.rdoc create mode 100644 Rakefile create mode 100644 VERSION create mode 100644 app/assets/images/.directory create mode 100644 app/assets/images/ajax-loader.gif create mode 100644 app/assets/images/blueprint_add.png create mode 100644 app/assets/images/blueprint_delete.png create mode 100644 app/assets/images/blueprint_info.png create mode 100644 app/assets/images/blueprint_notice.png create mode 100644 app/assets/images/dir.png create mode 100644 app/assets/images/favicon.ico create mode 100644 app/assets/images/favicon.png create mode 100644 app/assets/images/git.png create mode 100644 app/assets/images/jquery_ui/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 app/assets/images/jquery_ui/images/ui-bg_flat_75_ffffff_40x100.png create mode 100644 app/assets/images/jquery_ui/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 app/assets/images/jquery_ui/images/ui-bg_glass_65_ffffff_1x400.png create mode 100644 app/assets/images/jquery_ui/images/ui-bg_glass_75_dadada_1x400.png create mode 100644 app/assets/images/jquery_ui/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 app/assets/images/jquery_ui/images/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 app/assets/images/jquery_ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 app/assets/images/jquery_ui/images/ui-icons_222222_256x240.png create mode 100644 app/assets/images/jquery_ui/images/ui-icons_2e83ff_256x240.png create mode 100644 app/assets/images/jquery_ui/images/ui-icons_454545_256x240.png create mode 100644 app/assets/images/jquery_ui/images/ui-icons_888888_256x240.png create mode 100644 app/assets/images/jquery_ui/images/ui-icons_cd0a0a_256x240.png create mode 100644 app/assets/images/no_avatar.png create mode 100644 app/assets/images/rails.png create mode 100644 app/assets/images/txt.png create mode 100644 app/assets/javascripts/application.js create mode 100644 app/assets/javascripts/commits.js create mode 100644 app/assets/javascripts/dashboard.js.coffee create mode 100644 app/assets/javascripts/issues.js.coffee create mode 100644 app/assets/javascripts/jquery-ui-1.8.16.custom.min.js create mode 100644 app/assets/javascripts/jquery.ui.selectmenu.js create mode 100644 app/assets/javascripts/profile.js.coffee create mode 100644 app/assets/javascripts/projects.js create mode 100644 app/assets/stylesheets/application.css create mode 100644 app/assets/stylesheets/dashboard.css.scss create mode 100644 app/assets/stylesheets/highlight.css.scss create mode 100644 app/assets/stylesheets/issues.css.scss create mode 100644 app/assets/stylesheets/jquery.ui.selectmenu.css create mode 100644 app/assets/stylesheets/profile.css.scss create mode 100644 app/assets/stylesheets/projects.css.scss create mode 100644 app/controllers/admin/mailer_controller.rb create mode 100644 app/controllers/admin/projects_controller.rb create mode 100644 app/controllers/admin/team_members_controller.rb create mode 100644 app/controllers/admin/users_controller.rb create mode 100644 app/controllers/application_controller.rb create mode 100644 app/controllers/commits_controller.rb create mode 100644 app/controllers/dashboard_controller.rb create mode 100644 app/controllers/issues_controller.rb create mode 100644 app/controllers/keys_controller.rb create mode 100644 app/controllers/notes_controller.rb create mode 100644 app/controllers/profile_controller.rb create mode 100644 app/controllers/projects_controller.rb create mode 100644 app/controllers/team_members_controller.rb create mode 100644 app/helpers/admin/projects_helper.rb create mode 100644 app/helpers/admin/users_helper.rb create mode 100644 app/helpers/application_helper.rb create mode 100644 app/helpers/commits_helper.rb create mode 100644 app/helpers/dashboard_helper.rb create mode 100644 app/helpers/issues_helper.rb create mode 100644 app/helpers/keys_helper.rb create mode 100644 app/helpers/profile_helper.rb create mode 100644 app/helpers/projects_helper.rb create mode 100644 app/helpers/team_members_helper.rb create mode 100644 app/mailers/.gitkeep create mode 100644 app/mailers/notify.rb create mode 100644 app/models/.gitkeep create mode 100644 app/models/ability.rb create mode 100644 app/models/issue.rb create mode 100644 app/models/key.rb create mode 100644 app/models/note.rb create mode 100644 app/models/project.rb create mode 100644 app/models/user.rb create mode 100644 app/models/users_project.rb create mode 100644 app/uploaders/attachment_uploader.rb create mode 100644 app/views/admin/_top_menu.html.haml create mode 100644 app/views/admin/mailer/preview.html.haml create mode 100644 app/views/admin/projects/_form.html.haml create mode 100644 app/views/admin/projects/edit.html.haml create mode 100644 app/views/admin/projects/index.html.haml create mode 100644 app/views/admin/projects/new.html.haml create mode 100644 app/views/admin/projects/show.html.haml create mode 100644 app/views/admin/team_members/_form.html.haml create mode 100644 app/views/admin/team_members/edit.html.haml create mode 100644 app/views/admin/team_members/index.html.haml create mode 100644 app/views/admin/team_members/new.html.haml create mode 100644 app/views/admin/team_members/show.html.haml create mode 100644 app/views/admin/users/_form.html.haml create mode 100644 app/views/admin/users/edit.html.haml create mode 100644 app/views/admin/users/index.html.haml create mode 100644 app/views/admin/users/new.html.haml create mode 100644 app/views/admin/users/show.html.haml create mode 100644 app/views/commits/_commits.html.haml create mode 100644 app/views/commits/_diff.html.haml create mode 100644 app/views/commits/_index.html.haml create mode 100644 app/views/commits/index.html.haml create mode 100644 app/views/commits/index.js.erb create mode 100644 app/views/commits/show.html.haml create mode 100644 app/views/commits/show.js.haml create mode 100644 app/views/dashboard/index.html.haml create mode 100644 app/views/devise/confirmations/new.html.erb create mode 100644 app/views/devise/mailer/confirmation_instructions.html.erb create mode 100644 app/views/devise/mailer/reset_password_instructions.html.erb create mode 100644 app/views/devise/mailer/unlock_instructions.html.erb create mode 100644 app/views/devise/passwords/edit.html.erb create mode 100644 app/views/devise/passwords/new.html.erb create mode 100644 app/views/devise/registrations/edit.html.erb create mode 100644 app/views/devise/registrations/new.html.erb create mode 100644 app/views/devise/sessions/new.html.erb create mode 100644 app/views/devise/shared/_links.erb create mode 100644 app/views/devise/unlocks/new.html.erb create mode 100644 app/views/issues/_form.html.haml create mode 100644 app/views/issues/_issues.html.haml create mode 100644 app/views/issues/_show.html.haml create mode 100644 app/views/issues/create.js.haml create mode 100644 app/views/issues/edit.js.haml create mode 100644 app/views/issues/index.html.haml create mode 100644 app/views/issues/index.js.haml create mode 100644 app/views/issues/new.js.haml create mode 100644 app/views/issues/show.html.haml create mode 100644 app/views/issues/update.js.haml create mode 100644 app/views/keys/_form.html.haml create mode 100644 app/views/keys/_show.html.haml create mode 100644 app/views/keys/create.js.haml create mode 100644 app/views/keys/edit.html.haml create mode 100644 app/views/keys/index.html.haml create mode 100644 app/views/keys/new.html.haml create mode 100644 app/views/keys/new.js.haml create mode 100644 app/views/layouts/_flash.html.haml create mode 100644 app/views/layouts/_head_panel.html.erb create mode 100644 app/views/layouts/application.html.haml create mode 100644 app/views/layouts/notify.html.haml create mode 100644 app/views/notes/_form.html.haml create mode 100644 app/views/notes/_notes.html.haml create mode 100644 app/views/notes/_show.html.haml create mode 100644 app/views/notes/create.js.haml create mode 100644 app/views/notify/new_issue_email.html.haml create mode 100644 app/views/notify/new_user_email.html.haml create mode 100644 app/views/notify/note_commit_email.html.haml create mode 100644 app/views/notify/note_issue_email.html.haml create mode 100644 app/views/notify/note_wall_email.html.haml create mode 100644 app/views/profile/_top_menu.html.haml create mode 100644 app/views/profile/index.html.haml create mode 100644 app/views/profile/password.html.haml create mode 100644 app/views/profile/show.html.haml create mode 100644 app/views/projects/_form.html.haml create mode 100644 app/views/projects/_side_panel.html.haml create mode 100644 app/views/projects/_team.html.haml create mode 100644 app/views/projects/_top_menu.html.haml create mode 100644 app/views/projects/_tree.html.haml create mode 100644 app/views/projects/_tree_file.html.haml create mode 100644 app/views/projects/_tree_item.html.haml create mode 100644 app/views/projects/create.js.haml create mode 100644 app/views/projects/edit.html.erb create mode 100644 app/views/projects/empty.html.erb create mode 100644 app/views/projects/index.html.haml create mode 100644 app/views/projects/new.html.erb create mode 100644 app/views/projects/show.html.haml create mode 100644 app/views/projects/team.html.haml create mode 100644 app/views/projects/tree.html.erb create mode 100644 app/views/projects/tree.js.haml create mode 100644 app/views/projects/update.js.haml create mode 100644 app/views/projects/wall.html.haml create mode 100644 app/views/team_members/_form.html.haml create mode 100644 app/views/team_members/_show.html.haml create mode 100644 app/views/team_members/create.js.haml create mode 100644 app/views/team_members/new.js.haml create mode 100644 app/views/team_members/update.js.haml create mode 100644 config.ru create mode 100644 config/application.rb create mode 100644 config/boot.rb create mode 100644 config/database.yml create mode 100644 config/environment.rb create mode 100644 config/environments/development.rb create mode 100644 config/environments/production.rb create mode 100644 config/environments/test.rb create mode 100644 config/gitosis.yml create mode 100644 config/initializers/backtrace_silencers.rb create mode 100644 config/initializers/devise.rb create mode 100644 config/initializers/inflections.rb create mode 100644 config/initializers/load_config.rb create mode 100644 config/initializers/mime_types.rb create mode 100644 config/initializers/rails_footnotes.rb create mode 100644 config/initializers/secret_token.rb create mode 100644 config/initializers/session_store.rb create mode 100644 config/initializers/wrap_parameters.rb create mode 100644 config/locales/devise.en.yml create mode 100644 config/locales/en.yml create mode 100644 config/routes.rb create mode 100644 configure.rb create mode 100644 db/fixtures/development/001_admin.rb create mode 100644 db/fixtures/production/001_admin.rb create mode 100644 db/fixtures/test/001_repo.rb create mode 100644 db/migrate/20110913200833_devise_create_users.rb create mode 100644 db/migrate/20110913204141_create_projects.rb create mode 100644 db/migrate/20110914221600_create_users_projects.rb create mode 100644 db/migrate/20110915205627_add_private_flag_to_project.rb create mode 100644 db/migrate/20110915213352_create_keys.rb create mode 100644 db/migrate/20110916123731_add_name_to_user.rb create mode 100644 db/migrate/20110916162511_add_key_title_to_key.rb create mode 100644 db/migrate/20110917212932_add_identifier_to_key.rb create mode 100644 db/migrate/20110921192501_create_issues.rb create mode 100644 db/migrate/20110922110156_add_code_to_project.rb create mode 100644 db/migrate/20110923211333_add_status_to_issue.rb create mode 100644 db/migrate/20110924214549_create_rails_admin_histories_table.rb create mode 100644 db/migrate/20110924215658_add_admin_field_to_user.rb create mode 100644 db/migrate/20110926082616_remove_admin.rb create mode 100644 db/migrate/20110927130352_create_notes.rb create mode 100644 db/migrate/20110928140106_add_project_id_for_note.rb create mode 100644 db/migrate/20110928142747_change_noteable_id_for_note.rb create mode 100644 db/migrate/20110928161328_add_attachment_to_note.rb create mode 100644 db/migrate/20111005193700_add_allow_repo_creation_for_user.rb create mode 100644 db/pkey.example create mode 100644 db/schema.rb create mode 100644 db/seeds.rb create mode 100644 doc/README_FOR_APP create mode 100644 install/prepare.rb create mode 100644 lib/assets/.gitkeep create mode 100644 lib/file_size_validator.rb create mode 100644 lib/gitosis.rb create mode 100644 lib/tasks/.gitkeep create mode 100644 lib/utils.rb create mode 100644 log/.gitkeep create mode 100644 public/404.html create mode 100644 public/422.html create mode 100644 public/500.html create mode 100644 public/favicon.ico create mode 100644 public/index.html.example create mode 100644 public/robots.txt create mode 100755 script/rails create mode 100644 spec/factories.rb create mode 100644 spec/factory.rb create mode 100644 spec/models/issue_spec.rb create mode 100644 spec/models/key_spec.rb create mode 100644 spec/models/note_spec.rb create mode 100644 spec/models/project_security_spec.rb create mode 100644 spec/models/project_spec.rb create mode 100644 spec/models/user_spec.rb create mode 100644 spec/models/users_project_spec.rb create mode 100644 spec/monkeypatch.rb create mode 100644 spec/requests/admin/admin_projects_spec.rb create mode 100644 spec/requests/admin/admin_users_spec.rb create mode 100644 spec/requests/admin/security_spec.rb create mode 100644 spec/requests/commits_notes_spec.rb create mode 100644 spec/requests/commits_spec.rb create mode 100644 spec/requests/issues_notes_spec.rb create mode 100644 spec/requests/issues_spec.rb create mode 100644 spec/requests/keys_spec.rb create mode 100644 spec/requests/profile_spec.rb create mode 100644 spec/requests/projects_security_spec.rb create mode 100644 spec/requests/projects_spec.rb create mode 100644 spec/requests/projects_tree_spec.rb create mode 100644 spec/requests/projects_wall_spec.rb create mode 100644 spec/requests/team_members_spec.rb create mode 100644 spec/requests/top_panel_spec.rb create mode 100644 spec/requests/user_security_spec.rb create mode 100644 spec/seed_project.tar.gz create mode 100644 spec/spec_helper.rb create mode 100644 spec/support/js_patch.rb create mode 100644 spec/support/login.rb create mode 100644 spec/support/matchers.rb create mode 100644 spec/support/security.rb create mode 100644 spec/support/shared_examples.rb create mode 100644 spec/support/valid_commit.rb create mode 100644 vendor/assets/stylesheets/.gitkeep create mode 100644 vendor/assets/stylesheets/blueprint/ie.css create mode 100755 vendor/assets/stylesheets/blueprint/plugins/buttons/icons/cross.png create mode 100755 vendor/assets/stylesheets/blueprint/plugins/buttons/icons/key.png create mode 100755 vendor/assets/stylesheets/blueprint/plugins/buttons/icons/tick.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/buttons/readme.txt create mode 100644 vendor/assets/stylesheets/blueprint/plugins/buttons/screen.css create mode 100644 vendor/assets/stylesheets/blueprint/plugins/fancy-type/readme.txt create mode 100644 vendor/assets/stylesheets/blueprint/plugins/fancy-type/screen.css create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/icons/doc.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/icons/email.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/icons/external.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/icons/feed.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/icons/im.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/icons/lock.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/icons/pdf.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/icons/visited.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/icons/xls.png create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/readme.txt create mode 100644 vendor/assets/stylesheets/blueprint/plugins/link-icons/screen.css create mode 100644 vendor/assets/stylesheets/blueprint/plugins/rtl/readme.txt create mode 100644 vendor/assets/stylesheets/blueprint/plugins/rtl/screen.css create mode 100644 vendor/assets/stylesheets/blueprint/print.css create mode 100644 vendor/assets/stylesheets/blueprint/screen.css create mode 100644 vendor/assets/stylesheets/blueprint/src/forms.css create mode 100755 vendor/assets/stylesheets/blueprint/src/grid.css create mode 100644 vendor/assets/stylesheets/blueprint/src/grid.png create mode 100644 vendor/assets/stylesheets/blueprint/src/ie.css create mode 100755 vendor/assets/stylesheets/blueprint/src/print.css create mode 100755 vendor/assets/stylesheets/blueprint/src/reset.css create mode 100644 vendor/assets/stylesheets/blueprint/src/typography.css create mode 100644 vendor/assets/stylesheets/jquery_ui/jquery-ui-1.8.16.custom.css create mode 100644 vendor/plugins/.gitkeep diff --git a/.rails_footnotes b/.rails_footnotes new file mode 100644 index 00000000..1019a70a --- /dev/null +++ b/.rails_footnotes @@ -0,0 +1,3 @@ +#this code temporarily disables notes for all controllers +# Footnotes::Filter.notes = [] + diff --git a/.rspec b/.rspec new file mode 100644 index 00000000..53607ea5 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--colour diff --git a/.rvmrc b/.rvmrc new file mode 100644 index 00000000..8ad3b66d --- /dev/null +++ b/.rvmrc @@ -0,0 +1 @@ +rvm use 1.9.2-p290 diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 00000000..78d50e03 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,14 @@ +v 0.9.1 + - increassed test coverage + - design improvements + - new issue email notification + - updated app name + - issue redesigned + - issue can be edit +v 0.8.0 + - sytax highlight for main file types + - redesign + - stability + - security fixes + - increased test coverage + - email notification diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..a431f502 --- /dev/null +++ b/Gemfile @@ -0,0 +1,50 @@ +source 'http://rubygems.org' + +gem 'rails', '3.1.0' + +gem 'sqlite3' +gem 'devise', "1.4.7" +gem 'stamp' +gem 'will_paginate', '~> 3.0' +gem 'haml-rails' +gem 'jquery-rails' +gem 'grit' +gem "carrierwave" +gem 'six' +gem 'therubyracer' +gem 'faker' +gem 'seed-fu', :branch => 'rails-3-1', :git => 'git://github.com/mbleigh/seed-fu.git' +gem "lockfile" +gem "inifile" +gem "net-ssh" +gem "albino", :git => "git://github.com/randx/albino.git" +gem "kaminari" + +group :assets do + gem 'sass-rails', " ~> 3.1.0" + gem 'coffee-rails', "~> 3.1.0" + gem 'uglifier' +end + +group :development do + gem 'rails-footnotes', '>= 3.7.5.rc4' + gem 'annotate', :git => 'git://github.com/ctran/annotate_models.git' +end + +group :development, :test do + gem 'rspec-rails' + gem 'shoulda' + gem 'capybara' + gem 'autotest' + gem 'autotest-rails' + gem 'ruby-debug19', :require => 'ruby-debug' + gem 'awesome_print' + gem 'database_cleaner' + gem 'launchy' +end + + +group :test do + gem 'turn', :require => false + gem 'simplecov', :require => false +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..b389f143 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,266 @@ +GIT + remote: git://github.com/ctran/annotate_models.git + revision: cfeec96c9ca0fa5035b10be3d73e798cc4fc52f7 + specs: + annotate (2.4.1.beta1) + +GIT + remote: git://github.com/mbleigh/seed-fu.git + revision: 29fe8c61ca6cc4408115ea7475fe2647081bd348 + branch: rails-3-1 + specs: + seed-fu (2.0.1.rails31) + activerecord (~> 3.1.0.rc4) + activesupport (~> 3.1.0.rc4) + +GIT + remote: git://github.com/randx/albino.git + revision: 118380924969f3a856659f86ea1f40c1ba7bfcb1 + specs: + albino (1.3.3) + posix-spawn (>= 0.3.6) + +GEM + remote: http://rubygems.org/ + specs: + ZenTest (4.5.0) + actionmailer (3.1.0) + actionpack (= 3.1.0) + mail (~> 2.3.0) + actionpack (3.1.0) + activemodel (= 3.1.0) + activesupport (= 3.1.0) + builder (~> 3.0.0) + erubis (~> 2.7.0) + i18n (~> 0.6) + rack (~> 1.3.2) + rack-cache (~> 1.0.3) + rack-mount (~> 0.8.2) + rack-test (~> 0.6.1) + sprockets (~> 2.0.0) + activemodel (3.1.0) + activesupport (= 3.1.0) + bcrypt-ruby (~> 3.0.0) + builder (~> 3.0.0) + i18n (~> 0.6) + activerecord (3.1.0) + activemodel (= 3.1.0) + activesupport (= 3.1.0) + arel (~> 2.2.1) + tzinfo (~> 0.3.29) + activeresource (3.1.0) + activemodel (= 3.1.0) + activesupport (= 3.1.0) + activesupport (3.1.0) + multi_json (~> 1.0) + addressable (2.2.6) + ansi (1.3.0) + archive-tar-minitar (0.5.2) + arel (2.2.1) + autotest (4.4.6) + ZenTest (>= 4.4.1) + autotest-rails (4.1.1) + ZenTest (= 4.5) + awesome_print (0.4.0) + bcrypt-ruby (3.0.1) + builder (3.0.0) + capybara (1.0.1) + mime-types (>= 1.16) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + selenium-webdriver (~> 2.0) + xpath (~> 0.1.4) + carrierwave (0.5.7) + activesupport (~> 3.0) + childprocess (0.2.2) + ffi (~> 1.0.6) + coffee-rails (3.1.1) + coffee-script (>= 2.2.0) + railties (~> 3.1.0) + coffee-script (2.2.0) + coffee-script-source + execjs + coffee-script-source (1.1.2) + columnize (0.3.4) + database_cleaner (0.6.7) + devise (1.4.7) + bcrypt-ruby (~> 3.0) + orm_adapter (~> 0.0.3) + warden (~> 1.0.3) + diff-lcs (1.1.3) + erubis (2.7.0) + execjs (1.2.6) + multi_json (~> 1.0) + faker (0.9.5) + i18n (~> 0.4) + ffi (1.0.9) + grit (2.4.1) + diff-lcs (~> 1.1) + mime-types (~> 1.15) + haml (3.1.3) + haml-rails (0.3.4) + actionpack (~> 3.0) + activesupport (~> 3.0) + haml (~> 3.0) + railties (~> 3.0) + hike (1.2.1) + i18n (0.6.0) + inifile (0.4.1) + jquery-rails (1.0.14) + railties (~> 3.0) + thor (~> 0.14) + json_pure (1.5.4) + spruz (~> 0.2.8) + kaminari (0.12.4) + rails (>= 3.0.0) + launchy (2.0.5) + addressable (~> 2.2.6) + libv8 (3.3.10.2) + linecache19 (0.5.12) + ruby_core_source (>= 0.1.4) + lockfile (1.4.3) + mail (2.3.0) + i18n (>= 0.4.0) + mime-types (~> 1.16) + treetop (~> 1.4.8) + mime-types (1.16) + multi_json (1.0.3) + net-ssh (2.2.1) + nokogiri (1.5.0) + orm_adapter (0.0.5) + polyglot (0.3.2) + posix-spawn (0.3.6) + rack (1.3.2) + rack-cache (1.0.3) + rack (>= 0.4) + rack-mount (0.8.3) + rack (>= 1.0.0) + rack-ssl (1.3.2) + rack + rack-test (0.6.1) + rack (>= 1.0) + rails (3.1.0) + actionmailer (= 3.1.0) + actionpack (= 3.1.0) + activerecord (= 3.1.0) + activeresource (= 3.1.0) + activesupport (= 3.1.0) + bundler (~> 1.0) + railties (= 3.1.0) + rails-footnotes (3.7.5.rc4) + rails (>= 3.0.0) + railties (3.1.0) + actionpack (= 3.1.0) + activesupport (= 3.1.0) + rack-ssl (~> 1.3.2) + rake (>= 0.8.7) + rdoc (~> 3.4) + thor (~> 0.14.6) + rake (0.9.2) + rdoc (3.9.4) + rspec (2.6.0) + rspec-core (~> 2.6.0) + rspec-expectations (~> 2.6.0) + rspec-mocks (~> 2.6.0) + rspec-core (2.6.4) + rspec-expectations (2.6.0) + diff-lcs (~> 1.1.2) + rspec-mocks (2.6.0) + rspec-rails (2.6.1) + actionpack (~> 3.0) + activesupport (~> 3.0) + railties (~> 3.0) + rspec (~> 2.6.0) + ruby-debug-base19 (0.11.25) + columnize (>= 0.3.1) + linecache19 (>= 0.5.11) + ruby_core_source (>= 0.1.4) + ruby-debug19 (0.11.6) + columnize (>= 0.3.1) + linecache19 (>= 0.5.11) + ruby-debug-base19 (>= 0.11.19) + ruby_core_source (0.1.5) + archive-tar-minitar (>= 0.5.2) + rubyzip (0.9.4) + sass (3.1.7) + sass-rails (3.1.1) + actionpack (~> 3.1.0) + railties (~> 3.1.0) + sass (>= 3.1.4) + tilt (~> 1.3.2) + selenium-webdriver (2.5.0) + childprocess (>= 0.2.1) + ffi (>= 1.0.7) + json_pure + rubyzip + shoulda (2.11.3) + simplecov (0.5.3) + multi_json (~> 1.0.3) + simplecov-html (~> 0.5.3) + simplecov-html (0.5.3) + six (0.2.0) + sprockets (2.0.0) + hike (~> 1.2) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + spruz (0.2.13) + sqlite3 (1.3.4) + stamp (0.1.6) + therubyracer (0.9.4) + libv8 (~> 3.3.10) + thor (0.14.6) + tilt (1.3.3) + treetop (1.4.10) + polyglot + polyglot (>= 0.3.1) + turn (0.8.2) + ansi (>= 1.2.2) + tzinfo (0.3.29) + uglifier (1.0.3) + execjs (>= 0.3.0) + multi_json (>= 1.0.2) + warden (1.0.5) + rack (>= 1.0) + will_paginate (3.0.0) + xpath (0.1.4) + nokogiri (~> 1.3) + +PLATFORMS + ruby + +DEPENDENCIES + albino! + annotate! + autotest + autotest-rails + awesome_print + capybara + carrierwave + coffee-rails (~> 3.1.0) + database_cleaner + devise (= 1.4.7) + faker + grit + haml-rails + inifile + jquery-rails + kaminari + launchy + lockfile + net-ssh + rails (= 3.1.0) + rails-footnotes (>= 3.7.5.rc4) + rspec-rails + ruby-debug19 + sass-rails (~> 3.1.0) + seed-fu! + shoulda + simplecov + six + sqlite3 + stamp + therubyracer + turn + uglifier + will_paginate (~> 3.0) diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..7cecc248 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2011 Dmitriy Zaporozhets + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.rdoc b/README.rdoc new file mode 100644 index 00000000..3ac8c6c6 --- /dev/null +++ b/README.rdoc @@ -0,0 +1,21 @@ +== Welcome to GitLab + +GitLAb is a free Project/Repository managment application + +== Application details + +rails 3.1 +works only with gitosis +sqlite as default db + +== Getting Started + +1. At the command prompt, clone application: +2. Setup and configure gitosis https://help.ubuntu.com/community/Git but use "git" as gitosis user name +3. Change directory to app and run next commands: + ruby configure.rb # OR ruby configure.rb production | test | development +4. Check config/gitosis.yml file +5. Start rails application: + rails s + +6. Go to http://localhost:3000/ and you'll see project managment page diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..35b2f05c --- /dev/null +++ b/Rakefile @@ -0,0 +1,7 @@ +#!/usr/bin/env rake +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require File.expand_path('../config/application', __FILE__) + +Gitlab::Application.load_tasks diff --git a/VERSION b/VERSION new file mode 100644 index 00000000..f374f666 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.9.1 diff --git a/app/assets/images/.directory b/app/assets/images/.directory new file mode 100644 index 00000000..93a51f7c --- /dev/null +++ b/app/assets/images/.directory @@ -0,0 +1,4 @@ +[Dolphin] +ShowPreview=true +Timestamp=2011,9,14,20,34,18 +Version=2 diff --git a/app/assets/images/ajax-loader.gif b/app/assets/images/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ca7ada960568fff04400cda966fbdcb106abfa2 GIT binary patch literal 6820 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/blueprint_add.png b/app/assets/images/blueprint_add.png new file mode 100644 index 0000000000000000000000000000000000000000..0969428c865f152da486c9a8cc580e565a44bacd GIT binary patch literal 4544 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/blueprint_info.png b/app/assets/images/blueprint_info.png new file mode 100644 index 0000000000000000000000000000000000000000..8278b9da7af95d32b20874737e25bd147278c670 GIT binary patch literal 4512 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 RV8Q?Z002ovPDHLkV1kBFk8%J2 literal 0 HcmV?d00001 diff --git a/app/assets/images/dir.png b/app/assets/images/dir.png new file mode 100644 index 0000000000000000000000000000000000000000..bd941249c8797e0f13c4cd1235dc681ac8083433 GIT binary patch literal 485 zcmVMxZ8V0!t+`;Y=SCH)IKPdm;zP$R}ULiyv;!R~{7wO)X=ZcmE!;pFS`kJsy$wZ;_qaY#aVlftm`^b%;s20MrTT z@iVM%-kt{v!~7RQ@e0Ku3PTh|C{D=E--Ajl0VKr|o4sp-;~0eks|P3!Ar!5DgyIxb zLA|s_DkKY7{k_Q)hbR>7eb8ne%>h!FFSY@A$q`Zb)e4J6*>Q-%cpp1d%zFh(Ct;h7NS>XTv bjlTiDh#!C9+nP=Q0000vYhz#zuJz@P!dKp~(AL>x#lFaYJy!T45do8P~GGlTs0_3Ky8W5Z{NPHAt@>KUrbE=zp${#e*po(|Gd1s|KGoV&kxdj z{``3hpx(dc<`y58EnAj#>eMN_#Kfd+Dk`e~Z{5131=24gE%V>n%KG|*2@}fu`})g! zdwa{jfB()7(qCI!x4_WA=>LipE3!a*5N>X6o}{Lx4%B}etY1!6?tgSt^j4TWG7S_z zZ(?lv|MBC;${_L9mewgY);6y+H8lSN?bf<;=Z=QFyu$z3m{_d(Lqo!@o10nufA#8> zBuM|{Nt0VsQ&V>*CnxWI^7x57NWY?@(*M}lIIQ~f^9pubSz7-;dGeGqvb$hxkbY$) z<^S<<@mTe*UbQ;U*2eCCdRoTOPoF-4!}Q0GAM87J><9yy0n!f&%lLTg`ax>5va*kY z%y4#c`5X}*an;tw_Oq*t+f#`CyBeyhYX1}B6R_G3QUi<&PGA}+&CAW-n-HIPs=T~n z#qM3ZLqKvbfa$8Rpm5oY88ga3{NaTefc`3mA=IKEaI{L7G1F!TLu3$3LRfvb|8PU(Dp;p z(@z-g6|U3VctBxUftcon!xkM!uDnSOS?(YvSy#FHlNGC!a#%wDQ|3~6S^2F?@_%$% zw4_$3f7%tky8EPTr%}w+MJsi8s|ITB2@ZTD`aZn=pt#+}%*V#34&5%e_guNmQDvfs c%0F>++f46GOzWJ!0)5Be>FVdQ&MBb@0CXgQ?EnA( literal 0 HcmV?d00001 diff --git a/app/assets/images/git.png b/app/assets/images/git.png new file mode 100644 index 0000000000000000000000000000000000000000..cb5d0590efadff8b35007ac6f6dc07b2d6d326c9 GIT binary patch literal 21559 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 Ai2wiq literal 0 HcmV?d00001 diff --git a/app/assets/images/jquery_ui/images/ui-bg_flat_0_aaaaaa_40x100.png b/app/assets/images/jquery_ui/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/app/assets/images/jquery_ui/images/ui-bg_flat_75_ffffff_40x100.png b/app/assets/images/jquery_ui/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/app/assets/images/jquery_ui/images/ui-bg_glass_55_fbf9ee_1x400.png b/app/assets/images/jquery_ui/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/app/assets/images/jquery_ui/images/ui-bg_glass_65_ffffff_1x400.png b/app/assets/images/jquery_ui/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/app/assets/images/jquery_ui/images/ui-bg_glass_75_dadada_1x400.png b/app/assets/images/jquery_ui/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP{vDV26o)#~38k_!`W=^oo1w6ixmPC4R1b Tyd6G3lNdZ*{an^LB{Ts5`idse literal 0 HcmV?d00001 diff --git a/app/assets/images/jquery_ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/app/assets/images/jquery_ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/jquery_ui/images/ui-icons_2e83ff_256x240.png b/app/assets/images/jquery_ui/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..84defe6e8ab878a83d7ed145c4734e5e1117cf0f GIT binary patch literal 5355 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 X_Gc^EhHU=dFY}4IzFMt{L(KmGE`UUf literal 0 HcmV?d00001 diff --git a/app/assets/images/jquery_ui/images/ui-icons_454545_256x240.png b/app/assets/images/jquery_ui/images/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..59bd45b907c4fd965697774ce8c5fc6b2fd9c105 GIT binary patch literal 4369 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 oBo%DI*Kv;w;*%(i9W@f3_WCF#rGn literal 0 HcmV?d00001 diff --git a/app/assets/images/jquery_ui/images/ui-icons_cd0a0a_256x240.png b/app/assets/images/jquery_ui/images/ui-icons_cd0a0a_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..2ab019b73ec11a485fa09378f3a0e155194f6a5d GIT binary patch literal 4369 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 AQ~&?~ literal 0 HcmV?d00001 diff --git a/app/assets/images/txt.png b/app/assets/images/txt.png new file mode 100644 index 0000000000000000000000000000000000000000..f3638cb4e1e109a4989fe8b2895d8c7071ec6bf2 GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6UU<4VhG>Yg9yH7gc9dW{aP#=Q zMia*!O?^!o3q2G zY`JghdOyFg)mPme{y*5p+@0;BdH9~m9v0b*ytQqU7fyM}c7aikF>slX1N)CW2`^2< zSZ1pO)(nP%K>k9W%ONxF0r}D_j0`0W^Ot4LV!Fp<)$vV=p}}*LN}8-M1HiM%g8JmHAX7F_Nb6Mw<(8L7*1e|gF literal 0 HcmV?d00001 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 00000000..01e3b416 --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,18 @@ +// This is a manifest file that'll be compiled into including all the files listed below. +// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically +// be included in the compiled file accessible from http://example.com/assets/application.js +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// the compiled file. +// +//= require jquery +//= require jquery_ujs +//= require_tree . + +$(function(){ + $(".one_click_select").click(function(){ + $(this).select(); + }); + + $('select#branch').selectmenu({style:'popup', width:200}); + $('select#tag').selectmenu({style:'popup', width:200}); +}); diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js new file mode 100644 index 00000000..a62e9330 --- /dev/null +++ b/app/assets/javascripts/commits.js @@ -0,0 +1,9 @@ +$(document).ready(function(){ + $(".day-commits-table li.commit").live('click', function(e){ + if(e.target.nodeName != "A") { + location.href = $(this).attr("url"); + e.stopPropagation(); + return false; + } + }); +}); diff --git a/app/assets/javascripts/dashboard.js.coffee b/app/assets/javascripts/dashboard.js.coffee new file mode 100644 index 00000000..76156794 --- /dev/null +++ b/app/assets/javascripts/dashboard.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/javascripts/issues.js.coffee b/app/assets/javascripts/issues.js.coffee new file mode 100644 index 00000000..76156794 --- /dev/null +++ b/app/assets/javascripts/issues.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/javascripts/jquery-ui-1.8.16.custom.min.js b/app/assets/javascripts/jquery-ui-1.8.16.custom.min.js new file mode 100644 index 00000000..14c9064f --- /dev/null +++ b/app/assets/javascripts/jquery-ui-1.8.16.custom.min.js @@ -0,0 +1,791 @@ +/*! + * jQuery UI 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.16", +keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({propAttr:c.fn.prop||c.fn.attr,_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d= +this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this, +"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart": +"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight, +outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a, +"tabindex"),d=isNaN(b);return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&& +a.element[0].parentNode)for(var e=0;e0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted= +false;a.target==this._mouseDownEvent.target&&b.data(a.target,this.widgetName+".preventClickEvent",true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); +;/* + * jQuery UI Position 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Position + */ +(function(c){c.ui=c.ui||{};var n=/left|center|right/,o=/top|center|bottom/,t=c.fn.position,u=c.fn.offset;c.fn.position=function(b){if(!b||!b.of)return t.apply(this,arguments);b=c.extend({},b);var a=c(b.of),d=a[0],g=(b.collision||"flip").split(" "),e=b.offset?b.offset.split(" "):[0,0],h,k,j;if(d.nodeType===9){h=a.width();k=a.height();j={top:0,left:0}}else if(d.setTimeout){h=a.width();k=a.height();j={top:a.scrollTop(),left:a.scrollLeft()}}else if(d.preventDefault){b.at="left top";h=k=0;j={top:b.of.pageY, +left:b.of.pageX}}else{h=a.outerWidth();k=a.outerHeight();j=a.offset()}c.each(["my","at"],function(){var f=(b[this]||"").split(" ");if(f.length===1)f=n.test(f[0])?f.concat(["center"]):o.test(f[0])?["center"].concat(f):["center","center"];f[0]=n.test(f[0])?f[0]:"center";f[1]=o.test(f[1])?f[1]:"center";b[this]=f});if(g.length===1)g[1]=g[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(b.at[0]==="right")j.left+=h;else if(b.at[0]==="center")j.left+=h/2;if(b.at[1]==="bottom")j.top+= +k;else if(b.at[1]==="center")j.top+=k/2;j.left+=e[0];j.top+=e[1];return this.each(function(){var f=c(this),l=f.outerWidth(),m=f.outerHeight(),p=parseInt(c.curCSS(this,"marginLeft",true))||0,q=parseInt(c.curCSS(this,"marginTop",true))||0,v=l+p+(parseInt(c.curCSS(this,"marginRight",true))||0),w=m+q+(parseInt(c.curCSS(this,"marginBottom",true))||0),i=c.extend({},j),r;if(b.my[0]==="right")i.left-=l;else if(b.my[0]==="center")i.left-=l/2;if(b.my[1]==="bottom")i.top-=m;else if(b.my[1]==="center")i.top-= +m/2;i.left=Math.round(i.left);i.top=Math.round(i.top);r={left:i.left-p,top:i.top-q};c.each(["left","top"],function(s,x){c.ui.position[g[s]]&&c.ui.position[g[s]][x](i,{targetWidth:h,targetHeight:k,elemWidth:l,elemHeight:m,collisionPosition:r,collisionWidth:v,collisionHeight:w,offset:e,my:b.my,at:b.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(i,{using:b.using}))})};c.ui.position={fit:{left:function(b,a){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();b.left= +d>0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+= +a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b), +g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery); +;/* + * jQuery UI Draggable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Draggables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== +"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= +this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;if(b.iframeFix)d(b.iframeFix===true?"iframe":b.iframeFix).each(function(){d('
').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")});return true},_mouseStart:function(a){var b=this.options; +this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}); +this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);d.ui.ddmanager&&d.ui.ddmanager.dragStart(this,a);return true}, +_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b= +false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration, +10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},_mouseUp:function(a){this.options.iframeFix===true&&d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)});d.ui.ddmanager&&d.ui.ddmanager.dragStop(this,a);return d.ui.mouse.prototype._mouseUp.call(this,a)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle|| +!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone().removeAttr("id"):this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&& +a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent= +this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"), +10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"), +10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[a.containment=="document"?0:d(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,a.containment=="document"?0:d(window).scrollTop()-this.offset.relative.top-this.offset.parent.top, +(a.containment=="document"?0:d(window).scrollLeft())+d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a.containment=="document"?0:d(window).scrollTop())+(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&a.containment.constructor!=Array){a=d(a.containment);var b=a[0];if(b){a.offset();var c=d(b).css("overflow")!= +"hidden";this.containment=[(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0),(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0),(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"), +10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom];this.relative_container=a}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+ +this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&& +!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,h=a.pageY;if(this.originalPosition){var g;if(this.containment){if(this.relative_container){g=this.relative_container.offset();g=[this.containment[0]+g.left,this.containment[1]+g.top,this.containment[2]+g.left,this.containment[3]+g.top]}else g=this.containment;if(a.pageX-this.offset.click.leftg[2])e=g[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>g[3])h=g[3]+this.offset.click.top}if(b.grid){h=b.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/b.grid[1])*b.grid[1]:this.originalPageY;h=g?!(h-this.offset.click.topg[3])?h:!(h-this.offset.click.topg[2])?e:!(e-this.offset.click.left=0;i--){var j=c.snapElements[i].left,l=j+c.snapElements[i].width,k=c.snapElements[i].top,m=k+c.snapElements[i].height;if(j-e=j&&f<=l||h>=j&&h<=l||fl)&&(e>= +i&&e<=k||g>=i&&g<=k||ek);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), +top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle= +this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!e(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne", +nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var d=0;d');/sw|se|ne|nw/.test(f)&&g.css({zIndex:++a.zIndex});"se"==f&&g.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[f]=".ui-resizable-"+f;this.element.append(g)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor== +String)this.handles[i]=e(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=e(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}e(this.handles[i])}};this._renderAxis(this.element);this._handles=e(".ui-resizable-handle",this.element).disableSelection(); +this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();e(this.element).addClass("ui-resizable-autohide").hover(function(){if(!a.disabled){e(this).removeClass("ui-resizable-autohide");b._handles.show()}},function(){if(!a.disabled)if(!b.resizing){e(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy(); +var b=function(c){e(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a= +false;for(var c in this.handles)if(e(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()};if(d.is(".ui-draggable")||/absolute/.test(d.css("position")))d.css({position:"absolute",top:c.top,left:c.left});e.browser.opera&&/relative/.test(d.css("position"))&&d.css({position:"relative",top:"auto",left:"auto"}); +this._renderProxy();c=m(this.helper.css("left"));var f=m(this.helper.css("top"));if(a.containment){c+=e(a.containment).scrollLeft()||0;f+=e(a.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:c,top:f};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:c,top:f};this.sizeDiff= +{width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:this.originalSize.width/this.originalSize.height||1;a=e(".ui-resizable-"+this.axis).css("cursor");e("body").css("cursor",a=="auto"?this.axis+"-resize":a);d.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,d=this._change[this.axis]; +if(!d)return false;c=d.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false}, +_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var d=this._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName);d=f&&e.ui.hasScroll(d[0],"left")?0:c.sizeDiff.height;f=f?0:c.sizeDiff.width;f={width:c.helper.width()-f,height:c.helper.height()-d};d=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var g=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(e.extend(f, +{top:g,left:d}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}e("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",b);this._helper&&this.helper.remove();return false},_updateVirtualBoundaries:function(b){var a=this.options,c,d,f;a={minWidth:k(a.minWidth)?a.minWidth:0,maxWidth:k(a.maxWidth)?a.maxWidth:Infinity,minHeight:k(a.minHeight)?a.minHeight:0,maxHeight:k(a.maxHeight)?a.maxHeight: +Infinity};if(this._aspectRatio||b){b=a.minHeight*this.aspectRatio;d=a.minWidth/this.aspectRatio;c=a.maxHeight*this.aspectRatio;f=a.maxWidth/this.aspectRatio;if(b>a.minWidth)a.minWidth=b;if(d>a.minHeight)a.minHeight=d;if(cb.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(g)b.width=a.minWidth;if(h)b.height=a.minHeight;if(d)b.width=a.maxWidth;if(f)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&l)b.left=i-a.minWidth;if(d&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(f&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left= +null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+ +a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+ +c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]); +b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});e.extend(e.ui.resizable,{version:"1.8.16"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(), +10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize,function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top- +f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var l=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:l.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(r,function(n,o){if((n=(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(l.css("position"))){c._revertToRelativePosition=true;l.css({position:"absolute",top:"auto",left:"auto"})}l.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType? +e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};if(b._revertToRelativePosition){b._revertToRelativePosition=false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a= +e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-g};g=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(f,h&&g?{top:h,left:g}:{}),{duration:c.animateDuration,easing:c.animateEasing, +step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};d&&d.length&&e(d[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});e.ui.plugin.add("resizable","containment",{start:function(){var b=e(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof e?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement= +e(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}}else{var d=e(a),f=[];e(["Top","Right","Left","Bottom"]).each(function(i,j){f[i]=m(d.css("padding"+j))});b.containerOffset=d.offset();b.containerPosition=d.position();b.containerSize={height:d.innerHeight()-f[3],width:d.innerWidth()-f[1]};c=b.containerOffset; +var g=b.containerSize.height,h=b.containerSize.width;h=e.ui.hasScroll(a,"left")?a.scrollWidth:h;g=e.ui.hasScroll(a)?a.scrollHeight:g;b.parentData={element:a,left:c.left,top:c.top,width:h,height:g}}}},resize:function(b){var a=e(this).data("resizable"),c=a.options,d=a.containerOffset,f=a.position;b=a._aspectRatio||b.shiftKey;var g={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))g=d;if(f.left<(a._helper?d.left:0)){a.size.width+=a._helper?a.position.left-d.left: +a.position.left-g.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?d.left:0}if(f.top<(a._helper?d.top:0)){a.size.height+=a._helper?a.position.top-d.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?d.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-g.left:a.offset.left-g.left)+a.sizeDiff.width);d=Math.abs((a._helper?a.offset.top-g.top:a.offset.top- +d.top)+a.sizeDiff.height);f=a.containerElement.get(0)==a.element.parent().get(0);g=/relative|absolute/.test(a.containerElement.css("position"));if(f&&g)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(d+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-d;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=e(this).data("resizable"),a=b.options,c=b.containerOffset,d=b.containerPosition, +f=b.containerElement,g=e(b.helper),h=g.offset(),i=g.outerWidth()-b.sizeDiff.width;g=g.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g});b._helper&&!a.animate&&/static/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g})}});e.ui.plugin.add("resizable","ghost",{start:function(){var b=e(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25, +display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=e(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b= +e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height= +d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery); +;/* + * jQuery UI Selectable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"), +selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("
")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX, +c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");b.unselecting=true;f._trigger("unselecting", +c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=this;this.dragged=true;if(!this.options.disabled){var d= +this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.righti||a.bottomb&&a.rightg&&a.bottom *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){var a=this.options;this.containerCache={};this.element.addClass("ui-sortable"); +this.refresh();this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a=== +"disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&& +!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top, +left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]}; +this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!= +document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a); +return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0], +e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset(); +c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"): +this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null, +dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):d(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")}, +toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+jg&&b+la[this.floating?"width":"height"]?j:g0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith(); +if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), +this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),b=0;b=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h=0;b--){var c=this.items[b];if(!(c.instance!=this.currentContainer&&this.currentContainer&&c.item[0]!=this.currentItem[0])){var e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b= +this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f= +d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")|| +0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out", +a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h- +f)this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g- +this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?f:!(f-this.offset.click.left=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this, +this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop", +a,this._uiHash());for(e=0;e li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"); +a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); +if(b.navigation){var d=a.element.find("a").filter(b.navigationFilter).eq(0);if(d.length){var h=d.closest(".ui-accordion-header");a.active=h.length?h:d.closest(".ui-accordion-content").prev()}}a.active=a._findActive(a.active||b.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");a.active.next().addClass("ui-accordion-content-active");a._createIcons();a.resize();a.element.attr("role","tablist");a.headers.attr("role","tab").bind("keydown.accordion", +function(f){return a._keydown(f)}).next().attr("role","tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(f){a._clickHandler.call(a,f,this);f.preventDefault()})},_createIcons:function(){var a= +this.options;if(a.icons){c("").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"); +this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(a.autoHeight||a.fillHeight)b.css("height","");return c.Widget.prototype.destroy.call(this)},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons(); +b&&this._createIcons()}if(a=="disabled")this.headers.add(this.headers.next())[b?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(a){if(!(this.options.disabled||a.altKey||a.ctrlKey)){var b=c.ui.keyCode,d=this.headers.length,h=this.headers.index(a.target),f=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:f=this.headers[(h+1)%d];break;case b.LEFT:case b.UP:f=this.headers[(h-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},a.target); +a.preventDefault()}if(f){c(a.target).attr("tabIndex",-1);c(f).attr("tabIndex",0);f.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,b-c(this).innerHeight()+ +c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height("").height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a==="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=this.options; +if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]===this.active[0];d.active=d.collapsible&&b?false:this.headers.index(a);if(!(this.running||!d.collapsible&&b)){var h=this.active;j=a.next();g=this.active.next();e={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):j,oldContent:g};var f=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(j,g,e,b,f);h.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header); +if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);a.next().addClass("ui-accordion-content-active")}}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var g=this.active.next(), +e={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:g},j=this.active=c([]);this._toggle(j,g,e)}},_toggle:function(a,b,d,h,f){var g=this,e=g.options;g.toShow=a;g.toHide=b;g.data=d;var j=function(){if(g)return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data);g.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&h?{toShow:c([]),toHide:b,complete:j,down:f,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:j,down:f,autoHeight:e.autoHeight|| +e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;h=c.ui.accordion.animations;var i=e.duration,k=e.animated;if(k&&!h[k]&&!c.easing[k])k="slide";h[k]||(h[k]=function(l){this.slide(l,{easing:k,duration:i||700})});h[k](d)}else{if(e.collapsible&&h)a.toggle();else{b.hide();a.show()}j(true)}b.prev().attr({"aria-expanded":"false", +"aria-selected":"false",tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");if(this.toHide.length)this.toHide.parent()[0].className=this.toHide.parent()[0].className;this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.16", +animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),h=0,f={},g={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){g[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/); +f[i]={value:j[1],unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(g,{step:function(j,i){if(i.prop=="height")h=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=h*f[i.prop].value+f[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide", +paddingTop:"hide",paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery); +;/* + * jQuery UI Autocomplete 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function(d){var e=0;d.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var a=this,b=this.element[0].ownerDocument,g;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.propAttr("readOnly"))){g= +false;var f=d.ui.keyCode;switch(c.keyCode){case f.PAGE_UP:a._move("previousPage",c);break;case f.PAGE_DOWN:a._move("nextPage",c);break;case f.UP:a._move("previous",c);c.preventDefault();break;case f.DOWN:a._move("next",c);c.preventDefault();break;case f.ENTER:case f.NUMPAD_ENTER:if(a.menu.active){g=true;c.preventDefault()}case f.TAB:if(!a.menu.active)return;a.menu.select(c);break;case f.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!= +a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);break}}}).bind("keypress.autocomplete",function(c){if(g){g=false;c.preventDefault()}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)}; +this.menu=d("
    ").addClass("ui-autocomplete").appendTo(d(this.options.appendTo||"body",b)[0]).mousedown(function(c){var f=a.menu.element[0];d(c.target).closest(".ui-menu-item").length||setTimeout(function(){d(document).one("mousedown",function(h){h.target!==a.element[0]&&h.target!==f&&!d.ui.contains(f,h.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,f){f=f.item.data("item.autocomplete");false!==a._trigger("focus",c,{item:f})&&/^key/.test(c.originalEvent.type)&& +a.element.val(f.value)},selected:function(c,f){var h=f.item.data("item.autocomplete"),i=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=i;setTimeout(function(){a.previous=i;a.selectedItem=h},1)}false!==a._trigger("select",c,{item:h})&&a.element.val(h.value);a.term=a.element.val();a.close(c);a.selectedItem=h},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"); +d.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();d.Widget.prototype.destroy.call(this)},_setOption:function(a,b){d.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(d(b||"body",this.element[0].ownerDocument)[0]);a==="disabled"&& +b&&this.xhr&&this.xhr.abort()},_initSource:function(){var a=this,b,g;if(d.isArray(this.options.source)){b=this.options.source;this.source=function(c,f){f(d.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source==="string"){g=this.options.source;this.source=function(c,f){a.xhr&&a.xhr.abort();a.xhr=d.ajax({url:g,data:c,dataType:"json",autocompleteRequest:++e,success:function(h){this.autocompleteRequest===e&&f(h)},error:function(){this.autocompleteRequest===e&&f([])}})}}else this.source= +this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length").data("item.autocomplete",b).append(d("
    ").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});d.extend(d.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, +"\\$&")},filter:function(a,b){var g=new RegExp(d.ui.autocomplete.escapeRegex(b),"i");return d.grep(a,function(c){return g.test(c.label||c.value||c)})}})})(jQuery); +(function(d){d.widget("ui.menu",{_create:function(){var e=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(a){if(d(a.target).closest(".ui-menu-item a").length){a.preventDefault();e.select(a)}});this.refresh()},refresh:function(){var e=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", +-1).mouseenter(function(a){e.activate(a,d(this).parent())}).mouseleave(function(){e.deactivate()})},activate:function(e,a){this.deactivate();if(this.hasScroll()){var b=a.offset().top-this.element.offset().top,g=this.element.scrollTop(),c=this.element.height();if(b<0)this.element.scrollTop(g+b);else b>=c&&this.element.scrollTop(g+b-c+a.height())}this.active=a.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",e,{item:a})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); +this._trigger("blur");this.active=null}},next:function(e){this.move("next",".ui-menu-item:first",e)},previous:function(e){this.move("prev",".ui-menu-item:last",e)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(e,a,b){if(this.active){e=this.active[e+"All"](".ui-menu-item").eq(0);e.length?this.activate(b,e):this.activate(b,this.element.children(a))}else this.activate(b, +this.element.children(a))},nextPage:function(e){if(this.hasScroll())if(!this.active||this.last())this.activate(e,this.element.children(".ui-menu-item:first"));else{var a=this.active.offset().top,b=this.element.height(),g=this.element.children(".ui-menu-item").filter(function(){var c=d(this).offset().top-a-b+d(this).height();return c<10&&c>-10});g.length||(g=this.element.children(".ui-menu-item:last"));this.activate(e,g)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| +this.last()?":first":":last"))},previousPage:function(e){if(this.hasScroll())if(!this.active||this.first())this.activate(e,this.element.children(".ui-menu-item:last"));else{var a=this.active.offset().top,b=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var g=d(this).offset().top-a+b-d(this).height();return g<10&&g>-10});result.length||(result=this.element.children(".ui-menu-item:first"));this.activate(e,result)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| +this.first()?":last":":first"))},hasScroll:function(){return this.element.height()").addClass("ui-button-text").html(this.options.label).appendTo(a.empty()).text(),e=this.options.icons,f=e.primary&&e.secondary,d=[];if(e.primary||e.secondary){if(this.options.text)d.push("ui-button-text-icon"+(f?"s":e.primary?"-primary":"-secondary"));e.primary&&a.prepend("");e.secondary&&a.append("");if(!this.options.text){d.push(f?"ui-button-icons-only": +"ui-button-icon-only");this.hasTitle||a.attr("title",c)}}else d.push("ui-button-text-only");a.addClass(d.join(" "))}}});b.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(a,c){a==="disabled"&&this.buttons.button("option",a,c);b.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var a=this.element.css("direction")=== +"ltr";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(a?"ui-corner-left":"ui-corner-right").end().filter(":last").addClass(a?"ui-corner-right":"ui-corner-left").end().end()},destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"); +b.Widget.prototype.destroy.call(this)}})})(jQuery); +;/* + * jQuery UI Dialog 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function(c,l){var m={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},n={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true},o=c.attrFn||{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true,click:true};c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false, +position:{my:"center",at:"center",collision:"fit",using:function(a){var b=c(this).css(a).offset().top;b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
    ")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ +b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&!i.isDefaultPrevented()&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
    ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), +h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id", +e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); +a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d,e;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== +b.uiDialog[0]){e=c(this).css("z-index");isNaN(e)||(d=Math.max(d,e))}});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()};c.ui.dialog.maxZ+=1; +d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== +f[0]&&e.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false,e=c("
    ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("
    ").addClass("ui-dialog-buttonset").appendTo(e);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a, +function(){return!(d=true)});if(d){c.each(a,function(f,h){h=c.isFunction(h)?{click:h,text:f}:h;var i=c('').click(function(){h.click.apply(b.element[0],arguments)}).appendTo(g);c.each(h,function(j,k){if(j!=="click")j in o?i[j](k):i.attr(j,k)});c.fn.button&&i.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close", +handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition, +originalSize:f.originalSize,position:f.position,size:f.size}}a=a===l?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize", +f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0],e;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "): +[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,f){if(+b[g]===b[g]){d[g]=b[g];b[g]=f}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,a)}else a=c.ui.dialog.prototype.options.position;(e=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(c.extend({of:window},a));e||this.uiDialog.hide()},_setOptions:function(a){var b=this,d={},e=false;c.each(a,function(g,f){b._setOption(g,f); +if(g in m)e=true;if(g in n)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"): +e.removeClass("ui-dialog-disabled");break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||" "));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a= +this.options,b,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();e||this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height- +b,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.16",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "), +create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){var b=c.inArray(a,this.instances);b!=-1&&this.oldInstances.push(this.instances.splice(b,1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var d=0;c.each(this.instances,function(){d=Math.max(d,this.css("z-index"))});this.maxZ=d},height:function(){var a,b;if(c.browser.msie&& +c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(b.range==="min"||b.range==="max"?" ui-slider-range-"+b.range:""))}for(var j=c.length;j"); +this.handles=c.add(d(e.join("")).appendTo(a.element));this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(g){g.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(g){d(this).data("index.ui-slider-handle", +g)});this.handles.keydown(function(g){var k=true,l=d(this).data("index.ui-slider-handle"),i,h,m;if(!a.options.disabled){switch(g.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:k=false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");i=a._start(g,l);if(i===false)return}break}m=a.options.step;i=a.options.values&&a.options.values.length? +(h=a.values(l)):(h=a.value());switch(g.keyCode){case d.ui.keyCode.HOME:h=a._valueMin();break;case d.ui.keyCode.END:h=a._valueMax();break;case d.ui.keyCode.PAGE_UP:h=a._trimAlignValue(i+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:h=a._trimAlignValue(i-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(i===a._valueMax())return;h=a._trimAlignValue(i+m);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(i===a._valueMin())return;h=a._trimAlignValue(i- +m);break}a._slide(g,l,h);return k}}).keyup(function(g){var k=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(g,k);a._change(g,k);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy(); +return this},_mouseCapture:function(a){var b=this.options,c,f,e,j,g;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c=this._normValueFromMouse({x:a.pageX,y:a.pageY});f=this._valueMax()-this._valueMin()+1;j=this;this.handles.each(function(k){var l=Math.abs(c-j.values(k));if(f>l){f=l;e=d(this);g=k}});if(b.range===true&&this.values(1)===b.min){g+=1;e=d(this.handles[g])}if(this._start(a,g)===false)return false; +this._mouseSliding=true;j._handleIndex=g;e.addClass("ui-state-active").focus();b=e.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-e.width()/2,top:a.pageY-b.top-e.height()/2-(parseInt(e.css("borderTopWidth"),10)||0)-(parseInt(e.css("borderBottomWidth"),10)||0)+(parseInt(e.css("marginTop"),10)||0)};this.handles.hasClass("ui-state-hover")||this._slide(a,g,c);return this._animateOff=true},_mouseStart:function(){return true},_mouseDrag:function(a){var b= +this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;if(this.orientation==="horizontal"){b= +this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b); +c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var f;if(this.options.values&&this.options.values.length){f=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>f||b===1&&c1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}else if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;f=arguments[0];for(e=0;e=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a= +this.options.range,b=this.options,c=this,f=!this._animateOff?b.animate:false,e,j={},g,k,l,i;if(this.options.values&&this.options.values.length)this.handles.each(function(h){e=(c.values(h)-c._valueMin())/(c._valueMax()-c._valueMin())*100;j[c.orientation==="horizontal"?"left":"bottom"]=e+"%";d(this).stop(1,1)[f?"animate":"css"](j,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(h===0)c.range.stop(1,1)[f?"animate":"css"]({left:e+"%"},b.animate);if(h===1)c.range[f?"animate":"css"]({width:e- +g+"%"},{queue:false,duration:b.animate})}else{if(h===0)c.range.stop(1,1)[f?"animate":"css"]({bottom:e+"%"},b.animate);if(h===1)c.range[f?"animate":"css"]({height:e-g+"%"},{queue:false,duration:b.animate})}g=e});else{k=this.value();l=this._valueMin();i=this._valueMax();e=i!==l?(k-l)/(i-l)*100:0;j[c.orientation==="horizontal"?"left":"bottom"]=e+"%";this.handle.stop(1,1)[f?"animate":"css"](j,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[f?"animate":"css"]({width:e+"%"}, +b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[f?"animate":"css"]({width:100-e+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[f?"animate":"css"]({height:e+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[f?"animate":"css"]({height:100-e+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.16"})})(jQuery); +;/* + * jQuery UI Tabs 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(d,p){function u(){return++v}function w(){return++x}var v=0,x=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
    ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
  • #{label}
  • "},_create:function(){this._tabify(true)},_setOption:function(b,e){if(b=="selected")this.options.collapsible&& +e==this.options.selected||this.select(e);else{this.options[b]=e;this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+u()},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+w());return d.cookie.apply(null,[b].concat(d.makeArray(arguments)))},_ui:function(b,e){return{tab:b,panel:e,index:this.anchors.index(b)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b= +d(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(b){function e(g,f){g.css("display","");!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}var a=this,c=this.options,h=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=d(" > li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);this.anchors.each(function(g,f){var i=d(f).attr("href"),l=i.split("#")[0],q;if(l&&(l===location.toString().split("#")[0]|| +(q=d("base")[0])&&l===q.href)){i=f.hash;f.href=i}if(h.test(i))a.panels=a.panels.add(a.element.find(a._sanitizeSelector(i)));else if(i&&i!=="#"){d.data(f,"href.tabs",i);d.data(f,"load.tabs",i.replace(/#.*$/,""));i=a._tabId(f);f.href="#"+i;f=a.element.find("#"+i);if(!f.length){f=d(c.panelTemplate).attr("id",i).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else c.disabled.push(g)});if(b){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); +this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(c.selected===p){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){c.selected=g;return false}});if(typeof c.selected!=="number"&&c.cookie)c.selected=parseInt(a._cookie(),10);if(typeof c.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)c.selected= +this.lis.index(this.lis.filter(".ui-tabs-selected"));c.selected=c.selected||(this.lis.length?0:-1)}else if(c.selected===null)c.selected=-1;c.selected=c.selected>=0&&this.anchors[c.selected]||c.selected<0?c.selected:0;c.disabled=d.unique(c.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(c.selected,c.disabled)!=-1&&c.disabled.splice(d.inArray(c.selected,c.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); +if(c.selected>=0&&this.anchors.length){a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash)).removeClass("ui-tabs-hide");this.lis.eq(c.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[c.selected],a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash))[0]))});this.load(c.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else c.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")); +this.element[c.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");c.cookie&&this._cookie(c.selected,c.cookie);b=0;for(var j;j=this.lis[b];b++)d(j)[d.inArray(b,c.disabled)!=-1&&!d(j).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");c.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(c.event!=="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+ +g)};this.lis.bind("mouseover.tabs",function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(c.fx)if(d.isArray(c.fx)){m=c.fx[0];o=c.fx[1]}else m=o=c.fx;var r=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal", +function(){e(f,o);a._trigger("show",null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},s=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")}; +this.anchors.bind(c.event+".tabs",function(){var g=this,f=d(g).closest("li"),i=a.panels.filter(":not(.ui-tabs-hide)"),l=a.element.find(a._sanitizeSelector(g.hash));if(f.hasClass("ui-tabs-selected")&&!c.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a.panels.filter(":animated").length||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}c.selected=a.anchors.index(this);a.abort();if(c.collapsible)if(f.hasClass("ui-tabs-selected")){c.selected= +-1;c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){s(g,i)}).dequeue("tabs");this.blur();return false}else if(!i.length){c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this));this.blur();return false}c.cookie&&a._cookie(c.selected,c.cookie);if(l.length){i.length&&a.element.queue("tabs",function(){s(g,i)});a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier."; +d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",function(){return false})},_getIndex:function(b){if(typeof b=="string")b=this.anchors.index(this.anchors.filter("[href$="+b+"]"));return b},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e= +d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(c,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});b.cookie&&this._cookie(null,b.cookie);return this},add:function(b, +e,a){if(a===p)a=this.anchors.length;var c=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,b).replace(/#\{label\}/g,e));b=!b.indexOf("#")?b.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var j=c.element.find("#"+b);j.length||(j=d(h.panelTemplate).attr("id",b).data("destroy.tabs",true));j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);j.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]); +j.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");j.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){c._trigger("show",null,c._ui(c.anchors[0],c.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(b){b=this._getIndex(b);var e=this.options,a=this.lis.eq(b).remove(),c=this.panels.eq(b).remove(); +if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(b+(b+1=b?--h:h});this._tabify();this._trigger("remove",null,this._ui(a.find("a")[0],c[0]));return this},enable:function(b){b=this._getIndex(b);var e=this.options;if(d.inArray(b,e.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=b});this._trigger("enable",null, +this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(b){b=this._getIndex(b);var e=this.options;if(b!=e.selected){this.lis.eq(b).addClass("ui-state-disabled");e.disabled.push(b);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[b],this.panels[b]))}return this},select:function(b){b=this._getIndex(b);if(b==-1)if(this.options.collapsible&&this.options.selected!=-1)b=this.options.selected;else return this;this.anchors.eq(b).trigger(this.options.event+".tabs");return this}, +load:function(b){b=this._getIndex(b);var e=this,a=this.options,c=this.anchors.eq(b)[0],h=d.data(c,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(c,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(a.spinner){var j=d("span",c);j.data("label.tabs",j.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){e.element.find(e._sanitizeSelector(c.hash)).html(k);e._cleanup();a.cache&&d.data(c, +"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.error(k,n,b,c)}catch(m){}}}));e.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this}, +url:function(b,e){this.anchors.eq(b).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.16"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(b,e){var a=this,c=this.options,h=a._rotate||(a._rotate=function(j){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=c.selected;a.select(++k'))}function N(a){return a.bind("mouseout", +function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");b.length&&b.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");if(!(d.datepicker._isDisabledDatepicker(J.inline?a.parent()[0]:J.input[0])||!b.length)){b.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); +b.addClass("ui-state-hover");b.hasClass("ui-datepicker-prev")&&b.addClass("ui-datepicker-prev-hover");b.hasClass("ui-datepicker-next")&&b.addClass("ui-datepicker-next-hover")}})}function H(a,b){d.extend(a,b);for(var c in b)if(b[c]==null||b[c]==C)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.16"}});var B=(new Date).getTime(),J;d.extend(M.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv}, +setDefaults:function(a){H(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g, +"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:N(d('
    '))}},_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker", +function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b);b.settings.disabled&&this._disableDatepicker(a)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&b.append.remove();if(c){b.append=d(''+c+"");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c== +"focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('').addClass(this._triggerClass).html(f==""?c:d("").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker(): +d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;gh){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a, +b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),true);this._updateDatepicker(b);this._updateAlternate(b);b.settings.disabled&&this._disableDatepicker(a);b.dpDiv.css("display","block")}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+= +1;this._dialogInput=d('');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}H(a.settings,e||{});b=b&&b.constructor==Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/ +2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b= +d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e= +a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().removeClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=d(a),c=d.data(a, +"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().addClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f== +a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;for(var b=0;b-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||a;if(a.nodeName.toLowerCase()!="input")a=d("input", +a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);if(d.datepicker._curInst&&d.datepicker._curInst!=b){d.datepicker._datepickerShowing&&d.datepicker._triggerOnClose(d.datepicker._curInst);d.datepicker._curInst.dpDiv.stop(true,true)}var c=d.datepicker._get(b,"beforeShow");c=c?c.apply(a,[a,b]):{};if(c!==false){H(b.settings,c);b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value= +"";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.empty();b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b); +c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){var i=b.dpDiv.find("iframe.ui-datepicker-cover");if(i.length){var g=d.datepicker._getBorders(b.dpDiv);i.css({left:-g[0],top:-g[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex(d(a).zIndex()+1);d.datepicker._datepickerShowing= +true;d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}}},_updateDatepicker:function(a){this.maxRows=4;var b=d.datepicker._getBorders(a.dpDiv);J=a;a.dpDiv.empty().append(this._generateHTML(a));var c=a.dpDiv.find("iframe.ui-datepicker-cover");c.length&&c.css({left:-b[0],top:-b[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}); +a.dpDiv.find("."+this._dayOverClass+" a").mouseover();b=this._getNumberOfMonths(a);c=b[1];a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");c>1&&a.dpDiv.addClass("ui-datepicker-multi-"+c).css("width",17*c+"em");a.dpDiv[(b[0]!=1||b[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&& +!a.input.is(":disabled")&&a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var e=a.yearshtml;setTimeout(function(){e===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml);e=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(), +h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),j=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>j&&j>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b= +this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1||d.expr.filters.hidden(a));)a=a[b?"previousSibling":"nextSibling"];a=d(a).offset();return[a.left,a.top]},_triggerOnClose:function(a){var b=this._get(a,"onClose");if(b)b.apply(a.input?a.input[0]:null,[a.input?a.input.val():"",a])},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b); +this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();d.datepicker._triggerOnClose(b);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")}, +_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"): +0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e["selected"+(c=="M"? +"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a); +this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField"); +if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"? +b.toString():b+"";if(b=="")return null;var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;e=typeof e!="string"?e:(new Date).getFullYear()%100+parseInt(e,10);for(var f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,j=c=-1,l=-1,u=-1,k=false,o=function(p){(p=A+1-1){j=1;l=u;do{e=this._getDaysInMonth(c,j-1);if(l<=e)break;j++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,j-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=j||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd", +COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames: +null)||this._defaults.monthNames;var i=function(o){(o=k+1 +12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||a.input&& +a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),j=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay? +new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),k=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=k&&nn;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-j,1)),this._getFormatConfig(a)); +n=this._canAdjustMonth(a,-1,m,g)?''+n+"":f?"":''+n+"";var s=this._get(a,"nextText");s=!h?s:this.formatDate(s,this._daylightSavingAdjust(new Date(m, +g+j,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?''+s+"":f?"":''+s+"";j=this._get(a,"currentText");s=this._get(a,"gotoCurrent")&& +a.currentDay?u:b;j=!h?j:this.formatDate(j,s,this._getFormatConfig(a));h=!a.inline?'":"";e=e?'
    '+(c?h:"")+(this._isInRange(a,s)?'":"")+(c?"":h)+"
    ":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;j=this._get(a,"showWeek");s=this._get(a,"dayNames");this._get(a,"dayNamesShort");var q=this._get(a,"dayNamesMin"),A=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),D=this._get(a,"showOtherMonths"),K=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var E=this._getDefaultDate(a),w="",x=0;x1)switch(G){case 0:y+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:y+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:y+=" ui-datepicker-group-middle";t="";break}y+='">'}y+='
    '+(/all|left/.test(t)&& +x==0?c?f:n:"")+(/all|right/.test(t)&&x==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,k,o,x>0||G>0,A,v)+'
    ';var z=j?'":"";for(t=0;t<7;t++){var r=(t+h)%7;z+="=5?' class="ui-datepicker-week-end"':"")+'>'+q[r]+""}y+=z+"";z=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay, +z);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;z=Math.ceil((t+z)/7);this.maxRows=z=l?this.maxRows>z?this.maxRows:z:z;r=this._daylightSavingAdjust(new Date(m,g,1-t));for(var Q=0;Q";var R=!j?"":'";for(t=0;t<7;t++){var I=p?p.apply(a.input?a.input[0]:null,[r]):[true,""],F=r.getMonth()!=g,L=F&&!K||!I[0]||k&&ro;R+='";r.setDate(r.getDate()+1);r=this._daylightSavingAdjust(r)}y+=R+""}g++;if(g>11){g=0;m++}y+="
    '+this._get(a,"weekHeader")+"
    '+this._get(a,"calculateWeek")(r)+""+(F&&!D?" ":L?''+ +r.getDate()+"":''+r.getDate()+"")+"
    "+(l?""+(i[0]>0&&G==i[1]-1?'
    ':""):"");O+=y}w+=O}w+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'': +"");a._keyEvent=false;return w},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var j=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),k='
    ',o="";if(h||!j)o+=''+i[b]+"";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='"}u||(k+=o+(h||!(j&&l)?" ":""));if(!a.yearshtml){a.yearshtml="";if(h||!l)k+=''+c+"";else{g=this._get(a,"yearRange").split(":");var s=(new Date).getFullYear();i=function(q){q=q.match(/c[+-].*/)?c+parseInt(q.substring(1),10):q.match(/[+-].*/)?s+parseInt(q,10):parseInt(q,10);return isNaN(q)?s:q};b=i(g[0]);g=Math.max(b,i(g[1]||""));b=e?Math.max(b, +e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(a.yearshtml+='";k+=a.yearshtml;a.yearshtml=null}}k+=this._get(a,"yearSuffix");if(u)k+=(h||!(j&&l)?" ":"")+o;k+="
    ";return k},_adjustInstDate:function(a,b,c){var e=a.drawYear+(c=="Y"?b:0),f=a.drawMonth+ +(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&ba?a:b},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");if(b)b.apply(a.input? +a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);c=this._daylightSavingAdjust(new Date(c, +e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a, +"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=function(a){if(!this.length)return this; +if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));return this.each(function(){typeof a== +"string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new M;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.16";window["DP_jQuery_"+B]=d})(jQuery); +;/* + * jQuery UI Progressbar 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(b,d){b.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()});this.valueDiv=b("
    ").appendTo(this.element);this.oldValue=this._value();this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); +this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===d)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){if(a==="value"){this.options.value=c;this._refreshValue();this._value()===this.options.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100* +this._value()/this.options.max},_refreshValue:function(){var a=this.value(),c=this._percentage();if(this.oldValue!==a){this.oldValue=a;this._trigger("change")}this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(c.toFixed(0)+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.16"})})(jQuery); +;/* + * jQuery UI Effects 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/ + */ +jQuery.effects||function(f,j){function m(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], +16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return n.transparent;return n[f.trim(c).toLowerCase()]}function s(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return m(b)}function o(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, +a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function p(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in t||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function u(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d= +a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:b in f.fx.speeds?f.fx.speeds[b]:f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}function l(c){if(!c||typeof c==="number"||f.fx.speeds[c])return true;if(typeof c==="string"&&!f.effects[c])return true;return false}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor", +"borderTopColor","borderColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=s(b.elem,a);b.end=m(b.end);b.colorInit=true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var n={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0, +0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211, +211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},q=["add","remove","toggle"],t={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b, +d){if(f.isFunction(b)){d=b;b=null}return this.queue(function(){var e=f(this),g=e.attr("style")||" ",h=p(o.call(this)),r,v=e.attr("class");f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});r=p(o.call(this));e.attr("class",v);e.animate(u(h,r),{queue:false,duration:a,easing:b,complete:function(){f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments);f.dequeue(this)}})})}; +f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this, +[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.16",save:function(c,a){for(var b=0;b").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}), +d=document.activeElement;c.wrap(b);if(c[0]===d||f.contains(c[0],d))f(d).focus();b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(e,g){a[g]=c.css(g);if(isNaN(parseInt(a[g],10)))a[g]="auto"});c.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}return b.css(a).show()},removeWrapper:function(c){var a,b=document.activeElement; +if(c.parent().is(".ui-effects-wrapper")){a=c.parent().replaceWith(c);if(c[0]===b||f.contains(c[0],b))f(b).focus();return a}return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments),b={options:a[1],duration:a[2],callback:a[3]};a=b.options.mode;var d=f.effects[c];if(f.fx.off||!d)return a?this[a](b.duration,b.callback):this.each(function(){b.callback&&b.callback.call(this)}); +return d.call(this,b)},_show:f.fn.show,show:function(c){if(l(c))return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(l(c))return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(l(c)||typeof c==="boolean"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this, +arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/ +2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b, +d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c, +a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b, +d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ +e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); +;/* + * jQuery UI Effects Fade 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fade + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Fold 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","bottom","left","right"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1], +10)/100*f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); +;/* + * jQuery UI Effects Highlight 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& +this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Pulsate 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); +b.dequeue()})})}})(jQuery); +; \ No newline at end of file diff --git a/app/assets/javascripts/jquery.ui.selectmenu.js b/app/assets/javascripts/jquery.ui.selectmenu.js new file mode 100644 index 00000000..d61d75f9 --- /dev/null +++ b/app/assets/javascripts/jquery.ui.selectmenu.js @@ -0,0 +1,845 @@ + /* + * jQuery UI selectmenu dev version + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI + * https://github.com/fnagel/jquery-ui/wiki/Selectmenu + */ + +(function($) { + +$.widget("ui.selectmenu", { + getter: "value", + version: "1.8", + eventPrefix: "selectmenu", + options: { + transferClasses: true, + typeAhead: "sequential", + style: 'dropdown', + positionOptions: { + my: "left top", + at: "left bottom", + offset: null + }, + width: null, + menuWidth: null, + handleWidth: 26, + maxHeight: null, + icons: null, + format: null, + bgImage: function() {}, + wrapperElement: "
    " + }, + + _create: function() { + var self = this, o = this.options; + + // set a default id value, generate a new random one if not set by developer + var selectmenuId = this.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 ); + + // quick array of button and menu id's + this.ids = [ selectmenuId + '-button', selectmenuId + '-menu' ]; + + // define safe mouseup for future toggling + this._safemouseup = true; + + // create menu button wrapper + this.newelement = $( '', { + 'class': this.widgetBaseClass + ' ui-widget ui-state-default ui-corner-all', + 'id' : this.ids[ 0 ], + 'role': 'button', + 'href': '#nogo', + 'tabindex': this.element.attr( 'disabled' ) ? 1 : 0, + 'aria-haspopup': true, + 'aria-owns': this.ids[ 1 ] + }); + this.newelementWrap = $( o.wrapperElement ) + .append( this.newelement ) + .insertAfter( this.element ); + + // transfer tabindex + var tabindex = this.element.attr( 'tabindex' ); + if ( tabindex ) { + this.newelement.attr( 'tabindex', tabindex ); + } + + // save reference to select in data for ease in calling methods + this.newelement.data( 'selectelement', this.element ); + + // menu icon + this.selectmenuIcon = $( '' ) + .prependTo( this.newelement ); + + // append status span to button + this.newelement.prepend( '' ); + + // make associated form label trigger focus + $( 'label[for="' + selectmenuId + '"]' ) + .attr( 'for', this.ids[0] ) + .bind( 'click.selectmenu', function() { + self.newelement[0].focus(); + return false; + }); + + // click toggle for menu visibility + this.newelement + .bind('mousedown.selectmenu', function(event) { + self._toggle(event, true); + // make sure a click won't open/close instantly + if (o.style == "popup") { + self._safemouseup = false; + setTimeout(function() { self._safemouseup = true; }, 300); + } + return false; + }) + .bind('click.selectmenu', function() { + return false; + }) + .bind("keydown.selectmenu", function(event) { + var ret = false; + switch (event.keyCode) { + case $.ui.keyCode.ENTER: + ret = true; + break; + case $.ui.keyCode.SPACE: + self._toggle(event); + break; + case $.ui.keyCode.UP: + if (event.altKey) { + self.open(event); + } else { + self._moveSelection(-1); + } + break; + case $.ui.keyCode.DOWN: + if (event.altKey) { + self.open(event); + } else { + self._moveSelection(1); + } + break; + case $.ui.keyCode.LEFT: + self._moveSelection(-1); + break; + case $.ui.keyCode.RIGHT: + self._moveSelection(1); + break; + case $.ui.keyCode.TAB: + ret = true; + break; + default: + ret = true; + } + return ret; + }) + .bind('keypress.selectmenu', function(event) { + self._typeAhead(event.which, 'mouseup'); + return true; + }) + .bind('mouseover.selectmenu focus.selectmenu', function() { + if (!o.disabled) { + $(this).addClass(self.widgetBaseClass + '-focus ui-state-hover'); + } + }) + .bind('mouseout.selectmenu blur.selectmenu', function() { + if (!o.disabled) { + $(this).removeClass(self.widgetBaseClass + '-focus ui-state-hover'); + } + }); + + // document click closes menu + $(document).bind("mousedown.selectmenu", function(event) { + self.close(event); + }); + + // change event on original selectmenu + this.element + .bind("click.selectmenu", function() { + self._refreshValue(); + }) + // FIXME: newelement can be null under unclear circumstances in IE8 + // TODO not sure if this is still a problem (fnagel 20.03.11) + .bind("focus.selectmenu", function() { + if (self.newelement) { + self.newelement[0].focus(); + } + }); + + // set width when not set via options + if (!o.width) { + o.width = this.element.outerWidth(); + } + // set menu button width + this.newelement.width(o.width); + + // hide original selectmenu element + this.element.hide(); + + // create menu portion, append to body + this.list = $( '
    ').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), +top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle= +this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!e(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne", +nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var d=0;d');/sw|se|ne|nw/.test(f)&&g.css({zIndex:++a.zIndex});"se"==f&&g.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[f]=".ui-resizable-"+f;this.element.append(g)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor== +String)this.handles[i]=e(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=e(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}e(this.handles[i])}};this._renderAxis(this.element);this._handles=e(".ui-resizable-handle",this.element).disableSelection(); +this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();e(this.element).addClass("ui-resizable-autohide").hover(function(){if(!a.disabled){e(this).removeClass("ui-resizable-autohide");b._handles.show()}},function(){if(!a.disabled)if(!b.resizing){e(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy(); +var b=function(c){e(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a= +false;for(var c in this.handles)if(e(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()};if(d.is(".ui-draggable")||/absolute/.test(d.css("position")))d.css({position:"absolute",top:c.top,left:c.left});e.browser.opera&&/relative/.test(d.css("position"))&&d.css({position:"relative",top:"auto",left:"auto"}); +this._renderProxy();c=m(this.helper.css("left"));var f=m(this.helper.css("top"));if(a.containment){c+=e(a.containment).scrollLeft()||0;f+=e(a.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:c,top:f};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:c,top:f};this.sizeDiff= +{width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:this.originalSize.width/this.originalSize.height||1;a=e(".ui-resizable-"+this.axis).css("cursor");e("body").css("cursor",a=="auto"?this.axis+"-resize":a);d.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,d=this._change[this.axis]; +if(!d)return false;c=d.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false}, +_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var d=this._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName);d=f&&e.ui.hasScroll(d[0],"left")?0:c.sizeDiff.height;f=f?0:c.sizeDiff.width;f={width:c.helper.width()-f,height:c.helper.height()-d};d=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var g=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(e.extend(f, +{top:g,left:d}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}e("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",b);this._helper&&this.helper.remove();return false},_updateVirtualBoundaries:function(b){var a=this.options,c,d,f;a={minWidth:k(a.minWidth)?a.minWidth:0,maxWidth:k(a.maxWidth)?a.maxWidth:Infinity,minHeight:k(a.minHeight)?a.minHeight:0,maxHeight:k(a.maxHeight)?a.maxHeight: +Infinity};if(this._aspectRatio||b){b=a.minHeight*this.aspectRatio;d=a.minWidth/this.aspectRatio;c=a.maxHeight*this.aspectRatio;f=a.maxWidth/this.aspectRatio;if(b>a.minWidth)a.minWidth=b;if(d>a.minHeight)a.minHeight=d;if(cb.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(g)b.width=a.minWidth;if(h)b.height=a.minHeight;if(d)b.width=a.maxWidth;if(f)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&l)b.left=i-a.minWidth;if(d&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(f&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left= +null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+ +a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+ +c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]); +b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});e.extend(e.ui.resizable,{version:"1.8.16"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(), +10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize,function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top- +f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var l=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:l.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(r,function(n,o){if((n=(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(l.css("position"))){c._revertToRelativePosition=true;l.css({position:"absolute",top:"auto",left:"auto"})}l.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType? +e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};if(b._revertToRelativePosition){b._revertToRelativePosition=false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a= +e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-g};g=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(f,h&&g?{top:h,left:g}:{}),{duration:c.animateDuration,easing:c.animateEasing, +step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};d&&d.length&&e(d[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});e.ui.plugin.add("resizable","containment",{start:function(){var b=e(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof e?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement= +e(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}}else{var d=e(a),f=[];e(["Top","Right","Left","Bottom"]).each(function(i,j){f[i]=m(d.css("padding"+j))});b.containerOffset=d.offset();b.containerPosition=d.position();b.containerSize={height:d.innerHeight()-f[3],width:d.innerWidth()-f[1]};c=b.containerOffset; +var g=b.containerSize.height,h=b.containerSize.width;h=e.ui.hasScroll(a,"left")?a.scrollWidth:h;g=e.ui.hasScroll(a)?a.scrollHeight:g;b.parentData={element:a,left:c.left,top:c.top,width:h,height:g}}}},resize:function(b){var a=e(this).data("resizable"),c=a.options,d=a.containerOffset,f=a.position;b=a._aspectRatio||b.shiftKey;var g={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))g=d;if(f.left<(a._helper?d.left:0)){a.size.width+=a._helper?a.position.left-d.left: +a.position.left-g.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?d.left:0}if(f.top<(a._helper?d.top:0)){a.size.height+=a._helper?a.position.top-d.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?d.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-g.left:a.offset.left-g.left)+a.sizeDiff.width);d=Math.abs((a._helper?a.offset.top-g.top:a.offset.top- +d.top)+a.sizeDiff.height);f=a.containerElement.get(0)==a.element.parent().get(0);g=/relative|absolute/.test(a.containerElement.css("position"));if(f&&g)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(d+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-d;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=e(this).data("resizable"),a=b.options,c=b.containerOffset,d=b.containerPosition, +f=b.containerElement,g=e(b.helper),h=g.offset(),i=g.outerWidth()-b.sizeDiff.width;g=g.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g});b._helper&&!a.animate&&/static/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g})}});e.ui.plugin.add("resizable","ghost",{start:function(){var b=e(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25, +display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=e(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b= +e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height= +d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery); +;/* + * jQuery UI Selectable 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectables + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"), +selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("
    ")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX, +c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");b.unselecting=true;f._trigger("unselecting", +c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=this;this.dragged=true;if(!this.options.disabled){var d= +this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.righti||a.bottomb&&a.rightg&&a.bottom *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){var a=this.options;this.containerCache={};this.element.addClass("ui-sortable"); +this.refresh();this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a=== +"disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&& +!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top, +left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]}; +this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!= +document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a); +return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0], +e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset(); +c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"): +this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null, +dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):d(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")}, +toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+jg&&b+la[this.floating?"width":"height"]?j:g0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith(); +if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), +this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),b=0;b=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h=0;b--){var c=this.items[b];if(!(c.instance!=this.currentContainer&&this.currentContainer&&c.item[0]!=this.currentItem[0])){var e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b= +this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f= +d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")|| +0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out", +a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h- +f)this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g- +this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.topthis.containment[3])?g:!(g-this.offset.click.topthis.containment[2])?f:!(f-this.offset.click.left=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this, +this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop", +a,this._uiHash());for(e=0;e li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"); +a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); +if(b.navigation){var d=a.element.find("a").filter(b.navigationFilter).eq(0);if(d.length){var h=d.closest(".ui-accordion-header");a.active=h.length?h:d.closest(".ui-accordion-content").prev()}}a.active=a._findActive(a.active||b.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");a.active.next().addClass("ui-accordion-content-active");a._createIcons();a.resize();a.element.attr("role","tablist");a.headers.attr("role","tab").bind("keydown.accordion", +function(f){return a._keydown(f)}).next().attr("role","tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(f){a._clickHandler.call(a,f,this);f.preventDefault()})},_createIcons:function(){var a= +this.options;if(a.icons){c("").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"); +this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(a.autoHeight||a.fillHeight)b.css("height","");return c.Widget.prototype.destroy.call(this)},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons(); +b&&this._createIcons()}if(a=="disabled")this.headers.add(this.headers.next())[b?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(a){if(!(this.options.disabled||a.altKey||a.ctrlKey)){var b=c.ui.keyCode,d=this.headers.length,h=this.headers.index(a.target),f=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:f=this.headers[(h+1)%d];break;case b.LEFT:case b.UP:f=this.headers[(h-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},a.target); +a.preventDefault()}if(f){c(a.target).attr("tabIndex",-1);c(f).attr("tabIndex",0);f.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,b-c(this).innerHeight()+ +c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height("").height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a==="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=this.options; +if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]===this.active[0];d.active=d.collapsible&&b?false:this.headers.index(a);if(!(this.running||!d.collapsible&&b)){var h=this.active;j=a.next();g=this.active.next();e={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):j,oldContent:g};var f=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(j,g,e,b,f);h.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header); +if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);a.next().addClass("ui-accordion-content-active")}}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var g=this.active.next(), +e={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:g},j=this.active=c([]);this._toggle(j,g,e)}},_toggle:function(a,b,d,h,f){var g=this,e=g.options;g.toShow=a;g.toHide=b;g.data=d;var j=function(){if(g)return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data);g.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&h?{toShow:c([]),toHide:b,complete:j,down:f,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:j,down:f,autoHeight:e.autoHeight|| +e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;h=c.ui.accordion.animations;var i=e.duration,k=e.animated;if(k&&!h[k]&&!c.easing[k])k="slide";h[k]||(h[k]=function(l){this.slide(l,{easing:k,duration:i||700})});h[k](d)}else{if(e.collapsible&&h)a.toggle();else{b.hide();a.show()}j(true)}b.prev().attr({"aria-expanded":"false", +"aria-selected":"false",tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");if(this.toHide.length)this.toHide.parent()[0].className=this.toHide.parent()[0].className;this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.16", +animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),h=0,f={},g={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){g[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/); +f[i]={value:j[1],unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(g,{step:function(j,i){if(i.prop=="height")h=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=h*f[i.prop].value+f[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide", +paddingTop:"hide",paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery); +;/* + * jQuery UI Autocomplete 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function(d){var e=0;d.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var a=this,b=this.element[0].ownerDocument,g;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.propAttr("readOnly"))){g= +false;var f=d.ui.keyCode;switch(c.keyCode){case f.PAGE_UP:a._move("previousPage",c);break;case f.PAGE_DOWN:a._move("nextPage",c);break;case f.UP:a._move("previous",c);c.preventDefault();break;case f.DOWN:a._move("next",c);c.preventDefault();break;case f.ENTER:case f.NUMPAD_ENTER:if(a.menu.active){g=true;c.preventDefault()}case f.TAB:if(!a.menu.active)return;a.menu.select(c);break;case f.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!= +a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);break}}}).bind("keypress.autocomplete",function(c){if(g){g=false;c.preventDefault()}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)}; +this.menu=d("
      ").addClass("ui-autocomplete").appendTo(d(this.options.appendTo||"body",b)[0]).mousedown(function(c){var f=a.menu.element[0];d(c.target).closest(".ui-menu-item").length||setTimeout(function(){d(document).one("mousedown",function(h){h.target!==a.element[0]&&h.target!==f&&!d.ui.contains(f,h.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,f){f=f.item.data("item.autocomplete");false!==a._trigger("focus",c,{item:f})&&/^key/.test(c.originalEvent.type)&& +a.element.val(f.value)},selected:function(c,f){var h=f.item.data("item.autocomplete"),i=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=i;setTimeout(function(){a.previous=i;a.selectedItem=h},1)}false!==a._trigger("select",c,{item:h})&&a.element.val(h.value);a.term=a.element.val();a.close(c);a.selectedItem=h},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"); +d.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();d.Widget.prototype.destroy.call(this)},_setOption:function(a,b){d.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(d(b||"body",this.element[0].ownerDocument)[0]);a==="disabled"&& +b&&this.xhr&&this.xhr.abort()},_initSource:function(){var a=this,b,g;if(d.isArray(this.options.source)){b=this.options.source;this.source=function(c,f){f(d.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source==="string"){g=this.options.source;this.source=function(c,f){a.xhr&&a.xhr.abort();a.xhr=d.ajax({url:g,data:c,dataType:"json",autocompleteRequest:++e,success:function(h){this.autocompleteRequest===e&&f(h)},error:function(){this.autocompleteRequest===e&&f([])}})}}else this.source= +this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length").data("item.autocomplete",b).append(d("
      ").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});d.extend(d.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, +"\\$&")},filter:function(a,b){var g=new RegExp(d.ui.autocomplete.escapeRegex(b),"i");return d.grep(a,function(c){return g.test(c.label||c.value||c)})}})})(jQuery); +(function(d){d.widget("ui.menu",{_create:function(){var e=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(a){if(d(a.target).closest(".ui-menu-item a").length){a.preventDefault();e.select(a)}});this.refresh()},refresh:function(){var e=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", +-1).mouseenter(function(a){e.activate(a,d(this).parent())}).mouseleave(function(){e.deactivate()})},activate:function(e,a){this.deactivate();if(this.hasScroll()){var b=a.offset().top-this.element.offset().top,g=this.element.scrollTop(),c=this.element.height();if(b<0)this.element.scrollTop(g+b);else b>=c&&this.element.scrollTop(g+b-c+a.height())}this.active=a.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",e,{item:a})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); +this._trigger("blur");this.active=null}},next:function(e){this.move("next",".ui-menu-item:first",e)},previous:function(e){this.move("prev",".ui-menu-item:last",e)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(e,a,b){if(this.active){e=this.active[e+"All"](".ui-menu-item").eq(0);e.length?this.activate(b,e):this.activate(b,this.element.children(a))}else this.activate(b, +this.element.children(a))},nextPage:function(e){if(this.hasScroll())if(!this.active||this.last())this.activate(e,this.element.children(".ui-menu-item:first"));else{var a=this.active.offset().top,b=this.element.height(),g=this.element.children(".ui-menu-item").filter(function(){var c=d(this).offset().top-a-b+d(this).height();return c<10&&c>-10});g.length||(g=this.element.children(".ui-menu-item:last"));this.activate(e,g)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| +this.last()?":first":":last"))},previousPage:function(e){if(this.hasScroll())if(!this.active||this.first())this.activate(e,this.element.children(".ui-menu-item:last"));else{var a=this.active.offset().top,b=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var g=d(this).offset().top-a+b-d(this).height();return g<10&&g>-10});result.length||(result=this.element.children(".ui-menu-item:first"));this.activate(e,result)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| +this.first()?":last":":first"))},hasScroll:function(){return this.element.height()").addClass("ui-button-text").html(this.options.label).appendTo(a.empty()).text(),e=this.options.icons,f=e.primary&&e.secondary,d=[];if(e.primary||e.secondary){if(this.options.text)d.push("ui-button-text-icon"+(f?"s":e.primary?"-primary":"-secondary"));e.primary&&a.prepend("");e.secondary&&a.append("");if(!this.options.text){d.push(f?"ui-button-icons-only": +"ui-button-icon-only");this.hasTitle||a.attr("title",c)}}else d.push("ui-button-text-only");a.addClass(d.join(" "))}}});b.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(a,c){a==="disabled"&&this.buttons.button("option",a,c);b.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var a=this.element.css("direction")=== +"ltr";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(a?"ui-corner-left":"ui-corner-right").end().filter(":last").addClass(a?"ui-corner-right":"ui-corner-left").end().end()},destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"); +b.Widget.prototype.destroy.call(this)}})})(jQuery); +;/* + * jQuery UI Dialog 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function(c,l){var m={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},n={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true},o=c.attrFn||{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true,click:true};c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false, +position:{my:"center",at:"center",collision:"fit",using:function(a){var b=c(this).css(a).offset().top;b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
      ")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ +b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&!i.isDefaultPrevented()&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("
      ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), +h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id", +e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); +a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d,e;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== +b.uiDialog[0]){e=c(this).css("z-index");isNaN(e)||(d=Math.max(d,e))}});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()};c.ui.dialog.maxZ+=1; +d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== +f[0]&&e.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false,e=c("
      ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("
      ").addClass("ui-dialog-buttonset").appendTo(e);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a, +function(){return!(d=true)});if(d){c.each(a,function(f,h){h=c.isFunction(h)?{click:h,text:f}:h;var i=c('').click(function(){h.click.apply(b.element[0],arguments)}).appendTo(g);c.each(h,function(j,k){if(j!=="click")j in o?i[j](k):i.attr(j,k)});c.fn.button&&i.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close", +handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition, +originalSize:f.originalSize,position:f.position,size:f.size}}a=a===l?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize", +f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0],e;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "): +[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,f){if(+b[g]===b[g]){d[g]=b[g];b[g]=f}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,a)}else a=c.ui.dialog.prototype.options.position;(e=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(c.extend({of:window},a));e||this.uiDialog.hide()},_setOptions:function(a){var b=this,d={},e=false;c.each(a,function(g,f){b._setOption(g,f); +if(g in m)e=true;if(g in n)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"): +e.removeClass("ui-dialog-disabled");break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||" "));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a= +this.options,b,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();e||this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height- +b,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.16",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "), +create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){var b=c.inArray(a,this.instances);b!=-1&&this.oldInstances.push(this.instances.splice(b,1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var d=0;c.each(this.instances,function(){d=Math.max(d,this.css("z-index"))});this.maxZ=d},height:function(){var a,b;if(c.browser.msie&& +c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(b.range==="min"||b.range==="max"?" ui-slider-range-"+b.range:""))}for(var j=c.length;j"); +this.handles=c.add(d(e.join("")).appendTo(a.element));this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(g){g.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(g){d(this).data("index.ui-slider-handle", +g)});this.handles.keydown(function(g){var k=true,l=d(this).data("index.ui-slider-handle"),i,h,m;if(!a.options.disabled){switch(g.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:k=false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");i=a._start(g,l);if(i===false)return}break}m=a.options.step;i=a.options.values&&a.options.values.length? +(h=a.values(l)):(h=a.value());switch(g.keyCode){case d.ui.keyCode.HOME:h=a._valueMin();break;case d.ui.keyCode.END:h=a._valueMax();break;case d.ui.keyCode.PAGE_UP:h=a._trimAlignValue(i+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:h=a._trimAlignValue(i-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(i===a._valueMax())return;h=a._trimAlignValue(i+m);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(i===a._valueMin())return;h=a._trimAlignValue(i- +m);break}a._slide(g,l,h);return k}}).keyup(function(g){var k=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(g,k);a._change(g,k);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy(); +return this},_mouseCapture:function(a){var b=this.options,c,f,e,j,g;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c=this._normValueFromMouse({x:a.pageX,y:a.pageY});f=this._valueMax()-this._valueMin()+1;j=this;this.handles.each(function(k){var l=Math.abs(c-j.values(k));if(f>l){f=l;e=d(this);g=k}});if(b.range===true&&this.values(1)===b.min){g+=1;e=d(this.handles[g])}if(this._start(a,g)===false)return false; +this._mouseSliding=true;j._handleIndex=g;e.addClass("ui-state-active").focus();b=e.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-e.width()/2,top:a.pageY-b.top-e.height()/2-(parseInt(e.css("borderTopWidth"),10)||0)-(parseInt(e.css("borderBottomWidth"),10)||0)+(parseInt(e.css("marginTop"),10)||0)};this.handles.hasClass("ui-state-hover")||this._slide(a,g,c);return this._animateOff=true},_mouseStart:function(){return true},_mouseDrag:function(a){var b= +this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;if(this.orientation==="horizontal"){b= +this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b); +c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var f;if(this.options.values&&this.options.values.length){f=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>f||b===1&&c1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}else if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;f=arguments[0];for(e=0;e=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a= +this.options.range,b=this.options,c=this,f=!this._animateOff?b.animate:false,e,j={},g,k,l,i;if(this.options.values&&this.options.values.length)this.handles.each(function(h){e=(c.values(h)-c._valueMin())/(c._valueMax()-c._valueMin())*100;j[c.orientation==="horizontal"?"left":"bottom"]=e+"%";d(this).stop(1,1)[f?"animate":"css"](j,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(h===0)c.range.stop(1,1)[f?"animate":"css"]({left:e+"%"},b.animate);if(h===1)c.range[f?"animate":"css"]({width:e- +g+"%"},{queue:false,duration:b.animate})}else{if(h===0)c.range.stop(1,1)[f?"animate":"css"]({bottom:e+"%"},b.animate);if(h===1)c.range[f?"animate":"css"]({height:e-g+"%"},{queue:false,duration:b.animate})}g=e});else{k=this.value();l=this._valueMin();i=this._valueMax();e=i!==l?(k-l)/(i-l)*100:0;j[c.orientation==="horizontal"?"left":"bottom"]=e+"%";this.handle.stop(1,1)[f?"animate":"css"](j,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[f?"animate":"css"]({width:e+"%"}, +b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[f?"animate":"css"]({width:100-e+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[f?"animate":"css"]({height:e+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[f?"animate":"css"]({height:100-e+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.16"})})(jQuery); +;/* + * jQuery UI Tabs 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(d,p){function u(){return++v}function w(){return++x}var v=0,x=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
      ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
    • #{label}
    • "},_create:function(){this._tabify(true)},_setOption:function(b,e){if(b=="selected")this.options.collapsible&& +e==this.options.selected||this.select(e);else{this.options[b]=e;this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+u()},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+w());return d.cookie.apply(null,[b].concat(d.makeArray(arguments)))},_ui:function(b,e){return{tab:b,panel:e,index:this.anchors.index(b)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b= +d(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(b){function e(g,f){g.css("display","");!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}var a=this,c=this.options,h=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=d(" > li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);this.anchors.each(function(g,f){var i=d(f).attr("href"),l=i.split("#")[0],q;if(l&&(l===location.toString().split("#")[0]|| +(q=d("base")[0])&&l===q.href)){i=f.hash;f.href=i}if(h.test(i))a.panels=a.panels.add(a.element.find(a._sanitizeSelector(i)));else if(i&&i!=="#"){d.data(f,"href.tabs",i);d.data(f,"load.tabs",i.replace(/#.*$/,""));i=a._tabId(f);f.href="#"+i;f=a.element.find("#"+i);if(!f.length){f=d(c.panelTemplate).attr("id",i).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else c.disabled.push(g)});if(b){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); +this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(c.selected===p){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){c.selected=g;return false}});if(typeof c.selected!=="number"&&c.cookie)c.selected=parseInt(a._cookie(),10);if(typeof c.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)c.selected= +this.lis.index(this.lis.filter(".ui-tabs-selected"));c.selected=c.selected||(this.lis.length?0:-1)}else if(c.selected===null)c.selected=-1;c.selected=c.selected>=0&&this.anchors[c.selected]||c.selected<0?c.selected:0;c.disabled=d.unique(c.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(c.selected,c.disabled)!=-1&&c.disabled.splice(d.inArray(c.selected,c.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); +if(c.selected>=0&&this.anchors.length){a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash)).removeClass("ui-tabs-hide");this.lis.eq(c.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[c.selected],a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash))[0]))});this.load(c.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else c.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")); +this.element[c.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");c.cookie&&this._cookie(c.selected,c.cookie);b=0;for(var j;j=this.lis[b];b++)d(j)[d.inArray(b,c.disabled)!=-1&&!d(j).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");c.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(c.event!=="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+ +g)};this.lis.bind("mouseover.tabs",function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(c.fx)if(d.isArray(c.fx)){m=c.fx[0];o=c.fx[1]}else m=o=c.fx;var r=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal", +function(){e(f,o);a._trigger("show",null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},s=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")}; +this.anchors.bind(c.event+".tabs",function(){var g=this,f=d(g).closest("li"),i=a.panels.filter(":not(.ui-tabs-hide)"),l=a.element.find(a._sanitizeSelector(g.hash));if(f.hasClass("ui-tabs-selected")&&!c.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a.panels.filter(":animated").length||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}c.selected=a.anchors.index(this);a.abort();if(c.collapsible)if(f.hasClass("ui-tabs-selected")){c.selected= +-1;c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){s(g,i)}).dequeue("tabs");this.blur();return false}else if(!i.length){c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this));this.blur();return false}c.cookie&&a._cookie(c.selected,c.cookie);if(l.length){i.length&&a.element.queue("tabs",function(){s(g,i)});a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier."; +d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",function(){return false})},_getIndex:function(b){if(typeof b=="string")b=this.anchors.index(this.anchors.filter("[href$="+b+"]"));return b},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e= +d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(c,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});b.cookie&&this._cookie(null,b.cookie);return this},add:function(b, +e,a){if(a===p)a=this.anchors.length;var c=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,b).replace(/#\{label\}/g,e));b=!b.indexOf("#")?b.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var j=c.element.find("#"+b);j.length||(j=d(h.panelTemplate).attr("id",b).data("destroy.tabs",true));j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);j.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]); +j.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");j.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){c._trigger("show",null,c._ui(c.anchors[0],c.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(b){b=this._getIndex(b);var e=this.options,a=this.lis.eq(b).remove(),c=this.panels.eq(b).remove(); +if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(b+(b+1=b?--h:h});this._tabify();this._trigger("remove",null,this._ui(a.find("a")[0],c[0]));return this},enable:function(b){b=this._getIndex(b);var e=this.options;if(d.inArray(b,e.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=b});this._trigger("enable",null, +this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(b){b=this._getIndex(b);var e=this.options;if(b!=e.selected){this.lis.eq(b).addClass("ui-state-disabled");e.disabled.push(b);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[b],this.panels[b]))}return this},select:function(b){b=this._getIndex(b);if(b==-1)if(this.options.collapsible&&this.options.selected!=-1)b=this.options.selected;else return this;this.anchors.eq(b).trigger(this.options.event+".tabs");return this}, +load:function(b){b=this._getIndex(b);var e=this,a=this.options,c=this.anchors.eq(b)[0],h=d.data(c,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(c,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(a.spinner){var j=d("span",c);j.data("label.tabs",j.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){e.element.find(e._sanitizeSelector(c.hash)).html(k);e._cleanup();a.cache&&d.data(c, +"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.error(k,n,b,c)}catch(m){}}}));e.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this}, +url:function(b,e){this.anchors.eq(b).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.16"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(b,e){var a=this,c=this.options,h=a._rotate||(a._rotate=function(j){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=c.selected;a.select(++k'))}function N(a){return a.bind("mouseout", +function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");b.length&&b.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");if(!(d.datepicker._isDisabledDatepicker(J.inline?a.parent()[0]:J.input[0])||!b.length)){b.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); +b.addClass("ui-state-hover");b.hasClass("ui-datepicker-prev")&&b.addClass("ui-datepicker-prev-hover");b.hasClass("ui-datepicker-next")&&b.addClass("ui-datepicker-next-hover")}})}function H(a,b){d.extend(a,b);for(var c in b)if(b[c]==null||b[c]==C)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.16"}});var B=(new Date).getTime(),J;d.extend(M.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv}, +setDefaults:function(a){H(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g, +"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:N(d('
      '))}},_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker", +function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b);b.settings.disabled&&this._disableDatepicker(a)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&b.append.remove();if(c){b.append=d(''+c+"");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c== +"focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('').addClass(this._triggerClass).html(f==""?c:d("").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker(): +d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;gh){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a, +b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),true);this._updateDatepicker(b);this._updateAlternate(b);b.settings.disabled&&this._disableDatepicker(a);b.dpDiv.css("display","block")}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+= +1;this._dialogInput=d('');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}H(a.settings,e||{});b=b&&b.constructor==Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/ +2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b= +d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e= +a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().removeClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=d(a),c=d.data(a, +"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().addClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f== +a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;for(var b=0;b-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||a;if(a.nodeName.toLowerCase()!="input")a=d("input", +a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);if(d.datepicker._curInst&&d.datepicker._curInst!=b){d.datepicker._datepickerShowing&&d.datepicker._triggerOnClose(d.datepicker._curInst);d.datepicker._curInst.dpDiv.stop(true,true)}var c=d.datepicker._get(b,"beforeShow");c=c?c.apply(a,[a,b]):{};if(c!==false){H(b.settings,c);b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value= +"";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.empty();b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b); +c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){var i=b.dpDiv.find("iframe.ui-datepicker-cover");if(i.length){var g=d.datepicker._getBorders(b.dpDiv);i.css({left:-g[0],top:-g[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex(d(a).zIndex()+1);d.datepicker._datepickerShowing= +true;d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}}},_updateDatepicker:function(a){this.maxRows=4;var b=d.datepicker._getBorders(a.dpDiv);J=a;a.dpDiv.empty().append(this._generateHTML(a));var c=a.dpDiv.find("iframe.ui-datepicker-cover");c.length&&c.css({left:-b[0],top:-b[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}); +a.dpDiv.find("."+this._dayOverClass+" a").mouseover();b=this._getNumberOfMonths(a);c=b[1];a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");c>1&&a.dpDiv.addClass("ui-datepicker-multi-"+c).css("width",17*c+"em");a.dpDiv[(b[0]!=1||b[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&& +!a.input.is(":disabled")&&a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var e=a.yearshtml;setTimeout(function(){e===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml);e=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(), +h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),j=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>j&&j>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b= +this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1||d.expr.filters.hidden(a));)a=a[b?"previousSibling":"nextSibling"];a=d(a).offset();return[a.left,a.top]},_triggerOnClose:function(a){var b=this._get(a,"onClose");if(b)b.apply(a.input?a.input[0]:null,[a.input?a.input.val():"",a])},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b); +this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();d.datepicker._triggerOnClose(b);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")}, +_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"): +0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e["selected"+(c=="M"? +"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a); +this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField"); +if(b){var c=this._get(a,"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"? +b.toString():b+"";if(b=="")return null;var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;e=typeof e!="string"?e:(new Date).getFullYear()%100+parseInt(e,10);for(var f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,j=c=-1,l=-1,u=-1,k=false,o=function(p){(p=A+1-1){j=1;l=u;do{e=this._getDaysInMonth(c,j-1);if(l<=e)break;j++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,j-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=j||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd", +COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames: +null)||this._defaults.monthNames;var i=function(o){(o=k+1 +12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||a.input&& +a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),j=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay? +new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),k=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=k&&nn;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-j,1)),this._getFormatConfig(a)); +n=this._canAdjustMonth(a,-1,m,g)?''+n+"":f?"":''+n+"";var s=this._get(a,"nextText");s=!h?s:this.formatDate(s,this._daylightSavingAdjust(new Date(m, +g+j,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?''+s+"":f?"":''+s+"";j=this._get(a,"currentText");s=this._get(a,"gotoCurrent")&& +a.currentDay?u:b;j=!h?j:this.formatDate(j,s,this._getFormatConfig(a));h=!a.inline?'":"";e=e?'
      '+(c?h:"")+(this._isInRange(a,s)?'":"")+(c?"":h)+"
      ":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;j=this._get(a,"showWeek");s=this._get(a,"dayNames");this._get(a,"dayNamesShort");var q=this._get(a,"dayNamesMin"),A=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),D=this._get(a,"showOtherMonths"),K=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var E=this._getDefaultDate(a),w="",x=0;x1)switch(G){case 0:y+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:y+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:y+=" ui-datepicker-group-middle";t="";break}y+='">'}y+='
      '+(/all|left/.test(t)&& +x==0?c?f:n:"")+(/all|right/.test(t)&&x==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,k,o,x>0||G>0,A,v)+'
      ';var z=j?'":"";for(t=0;t<7;t++){var r=(t+h)%7;z+="=5?' class="ui-datepicker-week-end"':"")+'>'+q[r]+""}y+=z+"";z=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay, +z);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;z=Math.ceil((t+z)/7);this.maxRows=z=l?this.maxRows>z?this.maxRows:z:z;r=this._daylightSavingAdjust(new Date(m,g,1-t));for(var Q=0;Q";var R=!j?"":'";for(t=0;t<7;t++){var I=p?p.apply(a.input?a.input[0]:null,[r]):[true,""],F=r.getMonth()!=g,L=F&&!K||!I[0]||k&&ro;R+='";r.setDate(r.getDate()+1);r=this._daylightSavingAdjust(r)}y+=R+""}g++;if(g>11){g=0;m++}y+="
      '+this._get(a,"weekHeader")+"
      '+this._get(a,"calculateWeek")(r)+""+(F&&!D?" ":L?''+ +r.getDate()+"":''+r.getDate()+"")+"
      "+(l?""+(i[0]>0&&G==i[1]-1?'
      ':""):"");O+=y}w+=O}w+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'': +"");a._keyEvent=false;return w},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var j=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),k='
      ',o="";if(h||!j)o+=''+i[b]+"";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='"}u||(k+=o+(h||!(j&&l)?" ":""));if(!a.yearshtml){a.yearshtml="";if(h||!l)k+=''+c+"";else{g=this._get(a,"yearRange").split(":");var s=(new Date).getFullYear();i=function(q){q=q.match(/c[+-].*/)?c+parseInt(q.substring(1),10):q.match(/[+-].*/)?s+parseInt(q,10):parseInt(q,10);return isNaN(q)?s:q};b=i(g[0]);g=Math.max(b,i(g[1]||""));b=e?Math.max(b, +e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(a.yearshtml+='";k+=a.yearshtml;a.yearshtml=null}}k+=this._get(a,"yearSuffix");if(u)k+=(h||!(j&&l)?" ":"")+o;k+="
      ";return k},_adjustInstDate:function(a,b,c){var e=a.drawYear+(c=="Y"?b:0),f=a.drawMonth+ +(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&ba?a:b},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");if(b)b.apply(a.input? +a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);c=this._daylightSavingAdjust(new Date(c, +e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a, +"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=function(a){if(!this.length)return this; +if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));return this.each(function(){typeof a== +"string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new M;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.16";window["DP_jQuery_"+B]=d})(jQuery); +;/* + * jQuery UI Progressbar 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function(b,d){b.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()});this.valueDiv=b("
      ").appendTo(this.element);this.oldValue=this._value();this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); +this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===d)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){if(a==="value"){this.options.value=c;this._refreshValue();this._value()===this.options.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100* +this._value()/this.options.max},_refreshValue:function(){var a=this.value(),c=this._percentage();if(this.oldValue!==a){this.oldValue=a;this._trigger("change")}this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(c.toFixed(0)+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.16"})})(jQuery); +;/* + * jQuery UI Effects 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/ + */ +jQuery.effects||function(f,j){function m(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], +16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return n.transparent;return n[f.trim(c).toLowerCase()]}function s(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return m(b)}function o(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, +a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function p(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in t||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function u(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d= +a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:b in f.fx.speeds?f.fx.speeds[b]:f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}function l(c){if(!c||typeof c==="number"||f.fx.speeds[c])return true;if(typeof c==="string"&&!f.effects[c])return true;return false}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor", +"borderTopColor","borderColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=s(b.elem,a);b.end=m(b.end);b.colorInit=true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var n={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0, +0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211, +211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},q=["add","remove","toggle"],t={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b, +d){if(f.isFunction(b)){d=b;b=null}return this.queue(function(){var e=f(this),g=e.attr("style")||" ",h=p(o.call(this)),r,v=e.attr("class");f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});r=p(o.call(this));e.attr("class",v);e.animate(u(h,r),{queue:false,duration:a,easing:b,complete:function(){f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments);f.dequeue(this)}})})}; +f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this, +[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.16",save:function(c,a){for(var b=0;b").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}), +d=document.activeElement;c.wrap(b);if(c[0]===d||f.contains(c[0],d))f(d).focus();b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(e,g){a[g]=c.css(g);if(isNaN(parseInt(a[g],10)))a[g]="auto"});c.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}return b.css(a).show()},removeWrapper:function(c){var a,b=document.activeElement; +if(c.parent().is(".ui-effects-wrapper")){a=c.parent().replaceWith(c);if(c[0]===b||f.contains(c[0],b))f(b).focus();return a}return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments),b={options:a[1],duration:a[2],callback:a[3]};a=b.options.mode;var d=f.effects[c];if(f.fx.off||!d)return a?this[a](b.duration,b.callback):this.each(function(){b.callback&&b.callback.call(this)}); +return d.call(this,b)},_show:f.fn.show,show:function(c){if(l(c))return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(l(c))return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(l(c)||typeof c==="boolean"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this, +arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/ +2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b, +d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c, +a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b, +d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ +e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); +;/* + * jQuery UI Effects Fade 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fade + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Fold 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","bottom","left","right"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1], +10)/100*f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); +;/* + * jQuery UI Effects Highlight 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& +this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Pulsate 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); +b.dequeue()})})}})(jQuery); +; \ No newline at end of file diff --git a/app/assets/javascripts/jquery.cookie.js b/app/assets/javascripts/jquery.cookie.js new file mode 100644 index 00000000..6a3e394b --- /dev/null +++ b/app/assets/javascripts/jquery.cookie.js @@ -0,0 +1,41 @@ +/** + * jQuery Cookie plugin + * + * Copyright (c) 2010 Klaus Hartl (stilbuero.de) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ +jQuery.cookie = function (key, value, options) { + + // key and at least value given, set cookie... + if (arguments.length > 1 && String(value) !== "[object Object]") { + options = jQuery.extend({}, options); + + if (value === null || value === undefined) { + options.expires = -1; + } + + if (typeof options.expires === 'number') { + var days = options.expires, t = options.expires = new Date(); + t.setDate(t.getDate() + days); + } + + value = String(value); + + return (document.cookie = [ + encodeURIComponent(key), '=', + options.raw ? value : encodeURIComponent(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join('')); + } + + // key and possibly options given, get cookie... + options = value || {}; + var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent; + return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null; +}; diff --git a/app/assets/javascripts/jquery.ui.selectmenu.js b/app/assets/javascripts/jquery.ui.selectmenu.js new file mode 100644 index 00000000..d61d75f9 --- /dev/null +++ b/app/assets/javascripts/jquery.ui.selectmenu.js @@ -0,0 +1,845 @@ + /* + * jQuery UI selectmenu dev version + * + * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://docs.jquery.com/UI + * https://github.com/fnagel/jquery-ui/wiki/Selectmenu + */ + +(function($) { + +$.widget("ui.selectmenu", { + getter: "value", + version: "1.8", + eventPrefix: "selectmenu", + options: { + transferClasses: true, + typeAhead: "sequential", + style: 'dropdown', + positionOptions: { + my: "left top", + at: "left bottom", + offset: null + }, + width: null, + menuWidth: null, + handleWidth: 26, + maxHeight: null, + icons: null, + format: null, + bgImage: function() {}, + wrapperElement: "
      " + }, + + _create: function() { + var self = this, o = this.options; + + // set a default id value, generate a new random one if not set by developer + var selectmenuId = this.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 ); + + // quick array of button and menu id's + this.ids = [ selectmenuId + '-button', selectmenuId + '-menu' ]; + + // define safe mouseup for future toggling + this._safemouseup = true; + + // create menu button wrapper + this.newelement = $( '', { + 'class': this.widgetBaseClass + ' ui-widget ui-state-default ui-corner-all', + 'id' : this.ids[ 0 ], + 'role': 'button', + 'href': '#nogo', + 'tabindex': this.element.attr( 'disabled' ) ? 1 : 0, + 'aria-haspopup': true, + 'aria-owns': this.ids[ 1 ] + }); + this.newelementWrap = $( o.wrapperElement ) + .append( this.newelement ) + .insertAfter( this.element ); + + // transfer tabindex + var tabindex = this.element.attr( 'tabindex' ); + if ( tabindex ) { + this.newelement.attr( 'tabindex', tabindex ); + } + + // save reference to select in data for ease in calling methods + this.newelement.data( 'selectelement', this.element ); + + // menu icon + this.selectmenuIcon = $( '' ) + .prependTo( this.newelement ); + + // append status span to button + this.newelement.prepend( '' ); + + // make associated form label trigger focus + $( 'label[for="' + selectmenuId + '"]' ) + .attr( 'for', this.ids[0] ) + .bind( 'click.selectmenu', function() { + self.newelement[0].focus(); + return false; + }); + + // click toggle for menu visibility + this.newelement + .bind('mousedown.selectmenu', function(event) { + self._toggle(event, true); + // make sure a click won't open/close instantly + if (o.style == "popup") { + self._safemouseup = false; + setTimeout(function() { self._safemouseup = true; }, 300); + } + return false; + }) + .bind('click.selectmenu', function() { + return false; + }) + .bind("keydown.selectmenu", function(event) { + var ret = false; + switch (event.keyCode) { + case $.ui.keyCode.ENTER: + ret = true; + break; + case $.ui.keyCode.SPACE: + self._toggle(event); + break; + case $.ui.keyCode.UP: + if (event.altKey) { + self.open(event); + } else { + self._moveSelection(-1); + } + break; + case $.ui.keyCode.DOWN: + if (event.altKey) { + self.open(event); + } else { + self._moveSelection(1); + } + break; + case $.ui.keyCode.LEFT: + self._moveSelection(-1); + break; + case $.ui.keyCode.RIGHT: + self._moveSelection(1); + break; + case $.ui.keyCode.TAB: + ret = true; + break; + default: + ret = true; + } + return ret; + }) + .bind('keypress.selectmenu', function(event) { + self._typeAhead(event.which, 'mouseup'); + return true; + }) + .bind('mouseover.selectmenu focus.selectmenu', function() { + if (!o.disabled) { + $(this).addClass(self.widgetBaseClass + '-focus ui-state-hover'); + } + }) + .bind('mouseout.selectmenu blur.selectmenu', function() { + if (!o.disabled) { + $(this).removeClass(self.widgetBaseClass + '-focus ui-state-hover'); + } + }); + + // document click closes menu + $(document).bind("mousedown.selectmenu", function(event) { + self.close(event); + }); + + // change event on original selectmenu + this.element + .bind("click.selectmenu", function() { + self._refreshValue(); + }) + // FIXME: newelement can be null under unclear circumstances in IE8 + // TODO not sure if this is still a problem (fnagel 20.03.11) + .bind("focus.selectmenu", function() { + if (self.newelement) { + self.newelement[0].focus(); + } + }); + + // set width when not set via options + if (!o.width) { + o.width = this.element.outerWidth(); + } + // set menu button width + this.newelement.width(o.width); + + // hide original selectmenu element + this.element.hide(); + + // create menu portion, append to body + this.list = $( '
      <%= link_to truncate(@project.name, :length => 20), project_path(@project), :class => "current button" if @project && !@project.new_record? %> - <%= link_to 'Home', root_path, :class => current_page?(root_url) ? "current button" : "button" %> <%= link_to 'Projects', projects_path, :class => current_page?(projects_path) ? "current button" : "button" %> - <%= link_to 'Profile', profile_path, :class => (controller.controller_name == "keys") ? "current button" : "button" %> <%= link_to('Admin', admin_root_path, :class => admin_namespace? ? "current button" : "button" ) if current_user.is_admin? %> - <%#= link_to 'Profile', edit_user_registration_path, :class => "button" %> - <%= link_to 'Logout', destroy_user_session_path, :class => "button", :method => :delete %> + <%= link_to profile_path, :class => ((controller.controller_name == "keys" || controller.controller_name == "profile") ? "current button" : "button") do %> + <%= image_tag gravatar_icon(current_user.email) %> + <%= current_user.name.split(" ").first %> + <% end %> + <%= link_to 'Logout', destroy_user_session_path, :style => "border-left: 1px solid #666;", :class => "button", :method => :delete %>
      From e6bba9be4f0400471170e9d86f3ef15344416f2f Mon Sep 17 00:00:00 2001 From: VSizov Date: Sat, 15 Oct 2011 20:41:38 +0300 Subject: [PATCH 043/176] icon for handler of sortable --- app/assets/images/move.png | Bin 0 -> 260 bytes app/assets/stylesheets/projects.css.scss | 6 ++++++ app/views/issues/_show.html.haml | 3 ++- .../20111015154310_add_position_to_issues.rb | 5 +++++ 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 app/assets/images/move.png create mode 100644 db/migrate/20111015154310_add_position_to_issues.rb diff --git a/app/assets/images/move.png b/app/assets/images/move.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2d55ddf0b460d8effa80bca82340f5a6ca3341 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G%RF5iLn02poqmz?fC7)p-2)S?vfN&Ih#mZhV+8y*yN3R;9b3Rt`Fm-U`44i&Z04h&32%=!$C z3ttL6n7d0^>w$afvm-ty&cyXfhZ%pE%hb;j{2(RHu{Hg*tjyeRtIE%{xc4QB%L%&Z z$w(eO{9*T}G{%fgf0-1SzRbTA$oVSI;cnlG--@NqaZT~tEq}-F75I7u=wb#>S3j3^ HP6 dom_id(issue), :class => "issue", :url => project_issue_path(@project, issue) } %td - = image_tag gravatar_icon(issue.assignee.email), :class => ["left", "handle"], :width => 40, :style => "padding:0 5px;" + = image_tag "move.png" , :class => [:handle, :left] + = image_tag gravatar_icon(issue.assignee.email), :class => "left", :width => 40, :style => "padding:0 5px;" = truncate issue.assignee.name, :lenght => 20 %td ##{issue.id} %td= html_escape issue.title diff --git a/db/migrate/20111015154310_add_position_to_issues.rb b/db/migrate/20111015154310_add_position_to_issues.rb new file mode 100644 index 00000000..41451a0c --- /dev/null +++ b/db/migrate/20111015154310_add_position_to_issues.rb @@ -0,0 +1,5 @@ +class AddPositionToIssues < ActiveRecord::Migration + def change + add_column :issues, :position, :integer, :default => 0 + end +end From 526ad466c86e69c3447c192d8cae8da653556058 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Sat, 15 Oct 2011 21:08:38 +0300 Subject: [PATCH 044/176] fix issue sorting --- app/controllers/issues_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 1f507660..6da5dea8 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -71,7 +71,7 @@ class IssuesController < ApplicationController end def sort - @issues = @project.issues.all + @issues = @project.issues.where(:id => params['issue']) @issues.each do |issue| issue.position = params['issue'].index(issue.id.to_s) + 1 issue.save From 9265de3d25715aeafd38a4ef41596dca058dc18c Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 17 Oct 2011 00:07:10 +0300 Subject: [PATCH 045/176] snippets are ready --- app/assets/javascripts/snippets.js | 9 ++ app/assets/stylesheets/highlight.css.scss | 6 +- app/assets/stylesheets/projects.css.scss | 3 + app/assets/stylesheets/snippets.css.scss | 3 + app/controllers/notes_controller.rb | 2 + app/controllers/snippets_controller.rb | 63 +++++++++++ app/helpers/application_helper.rb | 2 +- app/helpers/snippets_helper.rb | 2 + app/models/ability.rb | 3 + app/models/project.rb | 1 + app/models/snippet.rb | 31 ++++++ app/views/projects/_form.html.haml | 4 +- app/views/projects/_top_menu.html.haml | 5 + app/views/snippets/_form.html.haml | 22 ++++ app/views/snippets/_snippet.html.haml | 11 ++ app/views/snippets/edit.html.haml | 1 + app/views/snippets/index.html.haml | 14 +++ app/views/snippets/new.html.haml | 1 + app/views/snippets/show.html.haml | 22 ++++ config/routes.rb | 2 + db/migrate/20111016183422_create_snippets.rb | 12 +++ ...1016193417_add_content_type_to_snippets.rb | 5 + ...0111016195506_add_file_name_to_snippets.rb | 6 ++ db/schema.rb | 12 ++- spec/factories.rb | 6 ++ spec/models/snippet_spec.rb | 16 +++ spec/requests/projects_security_spec.rb | 9 ++ spec/requests/snippets_spec.rb | 101 ++++++++++++++++++ 28 files changed, 366 insertions(+), 8 deletions(-) create mode 100644 app/assets/javascripts/snippets.js create mode 100644 app/assets/stylesheets/snippets.css.scss create mode 100644 app/controllers/snippets_controller.rb create mode 100644 app/helpers/snippets_helper.rb create mode 100644 app/models/snippet.rb create mode 100644 app/views/snippets/_form.html.haml create mode 100644 app/views/snippets/_snippet.html.haml create mode 100644 app/views/snippets/edit.html.haml create mode 100644 app/views/snippets/index.html.haml create mode 100644 app/views/snippets/new.html.haml create mode 100644 app/views/snippets/show.html.haml create mode 100644 db/migrate/20111016183422_create_snippets.rb create mode 100644 db/migrate/20111016193417_add_content_type_to_snippets.rb create mode 100644 db/migrate/20111016195506_add_file_name_to_snippets.rb create mode 100644 spec/models/snippet_spec.rb create mode 100644 spec/requests/snippets_spec.rb diff --git a/app/assets/javascripts/snippets.js b/app/assets/javascripts/snippets.js new file mode 100644 index 00000000..11e18eb7 --- /dev/null +++ b/app/assets/javascripts/snippets.js @@ -0,0 +1,9 @@ +$(document).ready(function(){ + $("#snippets-table .snippet").live('click', function(e){ + if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") { + location.href = $(this).attr("url"); + e.stopPropagation(); + return false; + } + }); +}); diff --git a/app/assets/stylesheets/highlight.css.scss b/app/assets/stylesheets/highlight.css.scss index 05cb98e7..31f9369a 100644 --- a/app/assets/stylesheets/highlight.css.scss +++ b/app/assets/stylesheets/highlight.css.scss @@ -22,8 +22,8 @@ td.linenos{ .highlight{ background:none; - padding:10px 0px 0px 0; - margin-left:10px; + padding:10px 0px 0px 10px; + margin-left:0px; } .highlight pre{ } @@ -43,7 +43,7 @@ td.linenos { } td.code .highlight { - overflow-x: scroll; + overflow: auto; } table.highlighttable pre{ padding:0; diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index bc15d8e2..2ea79dcc 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -310,6 +310,7 @@ input.ssh_project_url { } #projects-list .project, +#snippets-table .snippet, #issues-table .issue{ cursor:pointer; @@ -360,6 +361,8 @@ input.ssh_project_url { .user_new, .edit_user, .new_project, +.new_snippet, +.edit_snippet, .edit_project { input[type='text'], input[type='email'], diff --git a/app/assets/stylesheets/snippets.css.scss b/app/assets/stylesheets/snippets.css.scss new file mode 100644 index 00000000..1b680d87 --- /dev/null +++ b/app/assets/stylesheets/snippets.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Snippets controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index d0a40eb1..1703c00d 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -41,6 +41,8 @@ class NotesController < ApplicationController Notify.note_commit_email(u, @note).deliver when "Issue" then Notify.note_issue_email(u, @note).deliver + when "Snippet" + true else Notify.note_wall_email(u, @note).deliver end diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb new file mode 100644 index 00000000..5a6ffa4f --- /dev/null +++ b/app/controllers/snippets_controller.rb @@ -0,0 +1,63 @@ +class SnippetsController < ApplicationController + before_filter :authenticate_user! + before_filter :project + + # Authorize + before_filter :add_project_abilities + before_filter :authorize_read_snippet! + before_filter :authorize_write_snippet!, :only => [:new, :create, :close, :edit, :update, :sort] + + respond_to :html + + def index + @snippets = @project.snippets + end + + def new + @snippet = @project.snippets.new + end + + def create + @snippet = @project.snippets.new(params[:snippet]) + @snippet.author = current_user + @snippet.save + + if @snippet.valid? + redirect_to [@project, @snippet] + else + respond_with(@snippet) + end + end + + def edit + @snippet = @project.snippets.find(params[:id]) + end + + def update + @snippet = @project.snippets.find(params[:id]) + @snippet.update_attributes(params[:snippet]) + + if @snippet.valid? + redirect_to [@project, @snippet] + else + respond_with(@snippet) + end + end + + def show + @snippet = @project.snippets.find(params[:id]) + @notes = @snippet.notes + @note = @project.notes.new(:noteable => @snippet) + end + + def destroy + @snippet = @project.snippets.find(params[:id]) + authorize_admin_snippet! unless @snippet.author == current_user + + @snippet.destroy + + respond_to do |format| + format.js { render :nothing => true } + end + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 89a906f0..c389fd4a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -53,7 +53,7 @@ module ApplicationHelper [projects, default_nav, project_nav].flatten.to_json end - def handle_file_type(file_name, mime_type) + def handle_file_type(file_name, mime_type = nil) if file_name =~ /(\.rb|\.ru|\.rake|Rakefile|\.gemspec|\.rbx|Gemfile)$/ :ruby elsif file_name =~ /\.py$/ diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb new file mode 100644 index 00000000..236b6c8c --- /dev/null +++ b/app/helpers/snippets_helper.rb @@ -0,0 +1,2 @@ +module SnippetsHelper +end diff --git a/app/models/ability.rb b/app/models/ability.rb index 0a2c45f1..9a5970b5 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -12,6 +12,7 @@ class Ability rules << [ :read_project, :read_issue, + :read_snippet, :read_team_member, :read_note ] if project.readers.include?(user) @@ -19,12 +20,14 @@ class Ability rules << [ :write_project, :write_issue, + :write_snippet, :write_note ] if project.writers.include?(user) rules << [ :admin_project, :admin_issue, + :admin_snippet, :admin_team_member, :admin_note ] if project.admins.include?(user) diff --git a/app/models/project.rb b/app/models/project.rb index 3c07976d..3366b878 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -7,6 +7,7 @@ class Project < ActiveRecord::Base has_many :users_projects, :dependent => :destroy has_many :users, :through => :users_projects has_many :notes, :dependent => :destroy + has_many :snippets, :dependent => :destroy validates :name, :uniqueness => true, diff --git a/app/models/snippet.rb b/app/models/snippet.rb new file mode 100644 index 00000000..d51afc39 --- /dev/null +++ b/app/models/snippet.rb @@ -0,0 +1,31 @@ +class Snippet < ActiveRecord::Base + belongs_to :project + belongs_to :author, :class_name => "User" + has_many :notes, :as => :noteable + + attr_protected :author, :author_id, :project, :project_id + + validates_presence_of :project_id + validates_presence_of :author_id + + validates :title, + :presence => true, + :length => { :within => 0..255 } + + validates :file_name, + :presence => true, + :length => { :within => 0..255 } + + validates :content, + :presence => true, + :length => { :within => 0..10000 } + + + def self.content_types + [ + ".rb", ".py", ".pl", ".scala", ".c", ".cpp", ".java", + ".haml", ".html", ".sass", ".scss", ".xml", ".php", ".erb", + ".js", ".sh", ".coffee", ".yml", ".md" + ] + end +end diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index baa1f14f..9dbe57d2 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -1,8 +1,6 @@ = form_for(@project, :remote => true) do |f| %div.form_content - - if @project.new_record? - %h1 New Project - - else + - unless @project.new_record? %h1 Edit Project - if @project.errors.any? #error_explanation diff --git a/app/views/projects/_top_menu.html.haml b/app/views/projects/_top_menu.html.haml index b81ba6bb..fe4b72da 100644 --- a/app/views/projects/_top_menu.html.haml +++ b/app/views/projects/_top_menu.html.haml @@ -18,6 +18,11 @@ Wall - if @project.common_notes.count > 0 %span{ :class => "top_menu_count" }= @project.common_notes.count + %span + = link_to project_snippets_path(@project), :class => (controller.controller_name == "snippets") ? "current" : nil do + Snippets + - if @project.snippets.count > 0 + %span{ :class => "top_menu_count" }= @project.snippets.count - if @commit %span= link_to truncate(commit_name(@project,@commit), :length => 15), project_commit_path(@project, :id => @commit.id), :class => current_page?(:controller => "commits", :action => "show", :project_id => @project, :id => @commit.id) ? "current" : nil diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml new file mode 100644 index 00000000..571e2b06 --- /dev/null +++ b/app/views/snippets/_form.html.haml @@ -0,0 +1,22 @@ +%div + = form_for [@project, @snippet] do |f| + -if @snippet.errors.any? + %ul + - @snippet.errors.full_messages.each do |msg| + %li= msg + + %table.round-borders + %tr + %td= f.label :title + %td= f.text_field :title, :placeholder => "Example Snippet" + %tr + %td= f.label :file_name + %td= f.text_field :file_name, :placeholder => "example.rb" + %tr + %td{:colspan => 2} + = f.label :content, "Code" + %br + = f.text_area :content, :style => "height:240px;width:932px;" + + .actions.prepend-top + = f.submit 'Save', :class => "lbutton vm" diff --git a/app/views/snippets/_snippet.html.haml b/app/views/snippets/_snippet.html.haml new file mode 100644 index 00000000..483ff42c --- /dev/null +++ b/app/views/snippets/_snippet.html.haml @@ -0,0 +1,11 @@ +%tr{ :id => dom_id(snippet), :class => "snippet", :url => project_snippet_path(@project, snippet) } + %td + = image_tag gravatar_icon(snippet.author.email), :class => "left", :width => 40, :style => "padding:0 5px;" + = truncate snippet.author.name, :lenght => 20 + %td= html_escape snippet.title + %td= html_escape snippet.file_name + %td + - if can?(current_user, :admin_snippet, @project) || snippet.author == current_user + = link_to 'Edit', edit_project_snippet_path(@project, snippet), :class => "lbutton positive" + - if can?(current_user, :admin_snippet, @project) || snippet.author == current_user + = link_to 'Destroy', [@project, snippet], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-snippet negative", :id => "destroy_snippet_#{snippet.id}" diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml new file mode 100644 index 00000000..f81c0b8b --- /dev/null +++ b/app/views/snippets/edit.html.haml @@ -0,0 +1 @@ += render "snippets/form" diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml new file mode 100644 index 00000000..6e5dbde5 --- /dev/null +++ b/app/views/snippets/index.html.haml @@ -0,0 +1,14 @@ +%div + - if can? current_user, :write_snippet, @project + .left= link_to 'New Snippet', new_project_snippet_path(@project), :class => "lbutton vm" + + %table.round-borders#snippets-table + %tr + %th Author + %th Title + %th File name + %th + = render @snippets +:javascript + $('.delete-snippet').live('ajax:success', function() { + $(this).closest('tr').fadeOut(); }); diff --git a/app/views/snippets/new.html.haml b/app/views/snippets/new.html.haml new file mode 100644 index 00000000..f81c0b8b --- /dev/null +++ b/app/views/snippets/new.html.haml @@ -0,0 +1 @@ += render "snippets/form" diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml new file mode 100644 index 00000000..d29e0f8c --- /dev/null +++ b/app/views/snippets/show.html.haml @@ -0,0 +1,22 @@ +%h2 + = "Snippet ##{@snippet.id} - #{@snippet.title}" + +.view_file + .view_file_header + %strong + = @snippet.file_name + %br/ + .view_file_content + - ft = handle_file_type(@snippet.file_name) + :erb + <%= raw Albino.colorize(@snippet.content, ft, :html, 'utf-8', "linenos=True") %> + +- if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user + = link_to 'Edit', edit_project_snippet_path(@project, @snippet), :class => "lbutton positive" +- if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user + = link_to 'Destroy', [@project, @snippet], :confirm => 'Are you sure?', :method => :delete, :class => "lbutton delete-snippet negative", :id => "destroy_snippet_#{@snippet.id}" +%br +.snippet_notes= render "notes/notes" + +.clear + diff --git a/config/routes.rb b/config/routes.rb index acf92536..9ee3f0d0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -38,6 +38,8 @@ Gitlab::Application.routes.draw do } end + + resources :snippets resources :commits resources :team_members resources :issues do diff --git a/db/migrate/20111016183422_create_snippets.rb b/db/migrate/20111016183422_create_snippets.rb new file mode 100644 index 00000000..9b0bf201 --- /dev/null +++ b/db/migrate/20111016183422_create_snippets.rb @@ -0,0 +1,12 @@ +class CreateSnippets < ActiveRecord::Migration + def change + create_table :snippets do |t| + t.string :title + t.text :content + t.integer :author_id, :null => false + t.integer :project_id, :null => false + + t.timestamps + end + end +end diff --git a/db/migrate/20111016193417_add_content_type_to_snippets.rb b/db/migrate/20111016193417_add_content_type_to_snippets.rb new file mode 100644 index 00000000..511a6793 --- /dev/null +++ b/db/migrate/20111016193417_add_content_type_to_snippets.rb @@ -0,0 +1,5 @@ +class AddContentTypeToSnippets < ActiveRecord::Migration + def change + add_column :snippets, :content_type, :string, :null => false, :default => "txt" + end +end diff --git a/db/migrate/20111016195506_add_file_name_to_snippets.rb b/db/migrate/20111016195506_add_file_name_to_snippets.rb new file mode 100644 index 00000000..d378d225 --- /dev/null +++ b/db/migrate/20111016195506_add_file_name_to_snippets.rb @@ -0,0 +1,6 @@ +class AddFileNameToSnippets < ActiveRecord::Migration + def change + add_column :snippets, :file_name, :string + remove_column :snippets, :content_type + end +end diff --git a/db/schema.rb b/db/schema.rb index ed37dbbb..a8196976 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111015154310) do +ActiveRecord::Schema.define(:version => 20111016195506) do create_table "issues", :force => true do |t| t.string "title" @@ -56,6 +56,16 @@ ActiveRecord::Schema.define(:version => 20111015154310) do t.integer "owner_id" end + create_table "snippets", :force => true do |t| + t.string "title" + t.text "content" + t.integer "author_id", :null => false + t.integer "project_id", :null => false + t.datetime "created_at" + t.datetime "updated_at" + t.string "file_name" + end + create_table "users", :force => true do |t| t.string "email", :default => "", :null => false t.string "encrypted_password", :limit => 128, :default => "", :null => false diff --git a/spec/factories.rb b/spec/factories.rb index ea055d1b..cc0cd4e5 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -35,6 +35,12 @@ Factory.add(:issue, Issue) do |obj| obj.content = Faker::Lorem.sentences end +Factory.add(:snippet, Snippet) do |obj| + obj.title = Faker::Lorem.sentence + obj.file_name = Faker::Lorem.sentence + obj.content = Faker::Lorem.sentences +end + Factory.add(:note, Note) do |obj| obj.note = Faker::Lorem.sentence end diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb new file mode 100644 index 00000000..2a63584e --- /dev/null +++ b/spec/models/snippet_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe Snippet do + describe "Associations" do + it { should belong_to(:project) } + it { should belong_to(:author) } + end + + describe "Validation" do + it { should validate_presence_of(:title) } + it { should validate_presence_of(:author_id) } + it { should validate_presence_of(:project_id) } + it { should validate_presence_of(:file_name) } + it { should validate_presence_of(:content) } + end +end diff --git a/spec/requests/projects_security_spec.rb b/spec/requests/projects_security_spec.rb index a725a49c..a9b69c63 100644 --- a/spec/requests/projects_security_spec.rb +++ b/spec/requests/projects_security_spec.rb @@ -107,5 +107,14 @@ describe "Projects" do it { project_issues_path(@project).should be_denied_for :user } it { project_issues_path(@project).should be_denied_for :visitor } end + + describe "GET /project_code/snippets" do + it { project_snippets_path(@project).should be_allowed_for @u1 } + it { project_snippets_path(@project).should be_allowed_for @u3 } + it { project_snippets_path(@project).should be_denied_for :admin } + it { project_snippets_path(@project).should be_denied_for @u2 } + it { project_snippets_path(@project).should be_denied_for :user } + it { project_snippets_path(@project).should be_denied_for :visitor } + end end end diff --git a/spec/requests/snippets_spec.rb b/spec/requests/snippets_spec.rb new file mode 100644 index 00000000..00ae58da --- /dev/null +++ b/spec/requests/snippets_spec.rb @@ -0,0 +1,101 @@ +require 'spec_helper' + +describe "Snippets" do + let(:project) { Factory :project } + + before do + login_as :user + project.add_access(@user, :read, :write) + end + + describe "GET /snippets" do + before do + @snippet = Factory :snippet, + :author => @user, + :project => project + + visit project_snippets_path(project) + end + + subject { page } + + it { should have_content(@snippet.title) } + it { should have_content(@snippet.project.name) } + it { should have_content(@snippet.author.name) } + + describe "Destroy" do + before do + # admin access to remove snippet + @user.users_projects.destroy_all + project.add_access(@user, :read, :write, :admin) + visit project_snippets_path(project) + end + + it "should remove entry" do + expect { + click_link "destroy_snippet_#{@snippet.id}" + }.to change { Snippet.count }.by(-1) + end + end + end + + describe "New snippet" do + before do + visit project_snippets_path(project) + click_link "New Snippet" + end + + it "should open new snippet popup" do + page.current_path.should == new_project_snippet_path(project) + end + + describe "fill in" do + before do + fill_in "snippet_title", :with => "login function" + fill_in "snippet_file_name", :with => "test.rb" + fill_in "snippet_content", :with => "def login; end" + end + + it { expect { click_button "Save" }.to change {Snippet.count}.by(1) } + + it "should add new snippet to table" do + click_button "Save" + page.current_path.should == project_snippet_path(project, Snippet.last) + page.should have_content "login function" + page.should have_content "test.rb" + end + end + end + + describe "Edit snippet" do + before do + @snippet = Factory :snippet, + :author => @user, + :project => project + visit project_snippets_path(project) + click_link "Edit" + end + + it "should open edit page" do + page.current_path.should == edit_project_snippet_path(project, @snippet) + end + + describe "fill in" do + before do + fill_in "snippet_title", :with => "login function" + fill_in "snippet_file_name", :with => "test.rb" + fill_in "snippet_content", :with => "def login; end" + end + + it { expect { click_button "Save" }.to_not change {Snippet.count} } + + it "should update snippet fields" do + click_button "Save" + + page.current_path.should == project_snippet_path(project, @snippet) + page.should have_content "login function" + page.should have_content "test.rb" + end + end + end +end From bcf55312f7e59704b57f2cc4ef7893f55ffab770 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 17 Oct 2011 00:30:48 +0300 Subject: [PATCH 046/176] fixed #132 --- app/helpers/commits_helper.rb | 7 +++++++ app/views/commits/_commits.html.haml | 2 +- app/views/commits/show.html.haml | 2 +- app/views/projects/_tree_item.html.haml | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index f1b54668..4e7de84f 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -21,4 +21,11 @@ module CommitsHelper link_to "More", project_commits_path(@project, :offset => offset.to_i + limit.to_i, :limit => limit), :remote => true, :class => "lite_button vm", :style => "text-align:center; width:930px; ", :id => "more-commits-link" end + + def truncate_commit_message(commit, size = 60) + truncate(commit.message, :length => size) + # if special characters occurs + rescue + commit.message.length > size ? (commit.message[0..(size - 1)] + "...") : commit.message + end end diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index 4eebb83a..5a3ba3a7 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -11,7 +11,7 @@ = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" %p %strong - = commit.message.length > 60 ? (commit.message[0..59] + "...") : commit.message + = truncate_commit_message(commit) = link_to "Browse Code", tree_project_path(@project, :commit_id => commit.id), :class => "lite_button", :style => "float:right" = link_to truncate(commit.id.to_s, :length => 16), project_commit_path(@project, :id => commit.id), :class => "lite_button", :style => "width:120px;float:right" %span diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml index 147aaafb..a2c9149d 100644 --- a/app/views/commits/show.html.haml +++ b/app/views/commits/show.html.haml @@ -1,5 +1,5 @@ %h3 - = "[ #{@commit.committer} ] #{truncate @commit.message, :length => 80}" + = "[ #{@commit.committer} ] #{truncate_commit_message(@commit, 80)}" -#= link_to 'Back', project_commits_path(@project), :class => "button" %table.round-borders %tr diff --git a/app/views/projects/_tree_item.html.haml b/app/views/projects/_tree_item.html.haml index 9ba33c1e..4ebcfbef 100644 --- a/app/views/projects/_tree_item.html.haml +++ b/app/views/projects/_tree_item.html.haml @@ -12,4 +12,4 @@ = time_ago_in_words(content_commit.committed_date) ago %td - = link_to truncate(content_commit.message, :length => 40), project_commit_path(@project, content_commit) + = link_to truncate_commit_message(content_commit, 40), project_commit_path(@project, content_commit) From 8c8892460678471db1fce5129a0c2c7dd18f3b38 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 17 Oct 2011 01:14:48 +0300 Subject: [PATCH 047/176] fix #132 --- app/helpers/commits_helper.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 4e7de84f..b79e5718 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -22,10 +22,12 @@ module CommitsHelper :remote => true, :class => "lite_button vm", :style => "text-align:center; width:930px; ", :id => "more-commits-link" end + # Cause some errors with trucate & encoding use this method def truncate_commit_message(commit, size = 60) - truncate(commit.message, :length => size) + message = commit.message + message.length > size ? (message[0..(size - 1)] + "...") : message # if special characters occurs rescue - commit.message.length > size ? (commit.message[0..(size - 1)] + "...") : commit.message + commit.message end end From b08e4074b49acdb00dc9e041dab65a11462a090c Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 17 Oct 2011 11:34:53 +0300 Subject: [PATCH 048/176] updated changelog --- CHANGELOG | 17 +++++++++++++++++ VERSION | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 1201a857..aa846166 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,14 +1,30 @@ +v 1.1.0 + - feature: code snippets + - fixed horizontal scroll on file preview + - fixed app crash if commit message has invalid chars + - bugfix & code cleaning + +v 1.0.2 + - fixed bug with empty project + - added adv validation for project path & code + - feature: issues can be sortable + - bugfix + - username dispalyed on top panel + v 1.0.1 - fixed: with invalid source code for commit - fixed: lose branch/tag selection when use tree navigateion - when history clicked - display path - bug fix & code cleaning + v 1.0.0 - bug fix - projects preview mode + v 0.9.6 - css fix - new repo empty tree until restart server - fixed + v 0.9.4 - security improved - authorization improved @@ -24,6 +40,7 @@ v 0.9.1 - updated app name - issue redesigned - issue can be edit + v 0.8.0 - sytax highlight for main file types - redesign diff --git a/VERSION b/VERSION index 7dea76ed..6d7de6e6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.1 +1.0.2 From 783ca8979652085e2708cf3e020f3f83349dedb2 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 17 Oct 2011 13:39:03 +0300 Subject: [PATCH 049/176] security improved --- app/controllers/application_controller.rb | 8 ++++++-- app/controllers/issues_controller.rb | 14 +++++++++----- app/controllers/notes_controller.rb | 4 +++- app/controllers/snippets_controller.rb | 7 +++---- app/controllers/team_members_controller.rb | 4 ++-- app/models/ability.rb | 20 ++++++++++++++++++++ spec/requests/projects_security_spec.rb | 18 ++++++++++++------ spec/requests/user_security_spec.rb | 8 ++++---- spec/support/matchers.rb | 17 +++++++++++++++-- 9 files changed, 74 insertions(+), 26 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2866d1a7..047c6cb7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -27,11 +27,15 @@ class ApplicationController < ActionController::Base end def authenticate_admin! - return redirect_to(new_user_session_path) unless current_user.is_admin? + return render_404 unless current_user.is_admin? end def authorize_project!(action) - return redirect_to(new_user_session_path) unless can?(current_user, action, project) + return render_404 unless can?(current_user, action, project) + end + + def access_denied! + render_404 end def method_missing(method_sym, *arguments, &block) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 6da5dea8..cf8e1ebe 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -1,12 +1,12 @@ class IssuesController < ApplicationController before_filter :authenticate_user! before_filter :project + before_filter :issue, :only => [:edit, :update, :destroy, :show] # Authorize before_filter :add_project_abilities before_filter :authorize_read_issue! before_filter :authorize_write_issue!, :only => [:new, :create, :close, :edit, :update, :sort] - before_filter :authorize_admin_issue!, :only => [:destroy] respond_to :js @@ -30,12 +30,10 @@ class IssuesController < ApplicationController end def edit - @issue = @project.issues.find(params[:id]) respond_with(@issue) end def show - @issue = @project.issues.find(params[:id]) @notes = @issue.notes @note = @project.notes.new(:noteable => @issue) end @@ -51,7 +49,6 @@ class IssuesController < ApplicationController end def update - @issue = @project.issues.find(params[:id]) @issue.update_attributes(params[:issue]) respond_to do |format| @@ -62,7 +59,8 @@ class IssuesController < ApplicationController def destroy - @issue = @project.issues.find(params[:id]) + return access_denied! unless can?(current_user, :admin_issue, @issue) + @issue.destroy respond_to do |format| @@ -79,4 +77,10 @@ class IssuesController < ApplicationController render :nothing => true end + + protected + + def issue + @issue ||= @project.issues.find(params[:id]) + end end diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 1703c00d..46425664 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -4,7 +4,6 @@ class NotesController < ApplicationController # Authorize before_filter :add_project_abilities before_filter :authorize_write_note!, :only => [:create] - before_filter :authorize_admin_note!, :only => [:destroy] respond_to :js @@ -25,6 +24,9 @@ class NotesController < ApplicationController def destroy @note = @project.notes.find(params[:id]) + + return access_denied! unless can?(current_user, :admin_note, @note) + @note.destroy respond_to do |format| diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 5a6ffa4f..b31fe683 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -52,12 +52,11 @@ class SnippetsController < ApplicationController def destroy @snippet = @project.snippets.find(params[:id]) - authorize_admin_snippet! unless @snippet.author == current_user + + return access_denied! unless can?(current_user, :admin_snippet, @snippet) @snippet.destroy - respond_to do |format| - format.js { render :nothing => true } - end + redirect_to project_snippets_path(@project) end end diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb index e00cc36c..5fb2710d 100644 --- a/app/controllers/team_members_controller.rb +++ b/app/controllers/team_members_controller.rb @@ -3,8 +3,8 @@ class TeamMembersController < ApplicationController # Authorize before_filter :add_project_abilities - before_filter :authorize_read_team_member! - before_filter :authorize_admin_team_member!, :only => [:new, :create, :destroy, :update] + before_filter :authorize_read_project! + before_filter :authorize_admin_project!, :only => [:new, :create, :destroy, :update] def show @team_member = project.users_projects.find(params[:id]) diff --git a/app/models/ability.rb b/app/models/ability.rb index 9a5970b5..b822f630 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -2,6 +2,9 @@ class Ability def self.allowed(object, subject) case subject.class.name when "Project" then project_abilities(object, subject) + when "Issue" then issue_abilities(object, subject) + when "Note" then note_abilities(object, subject) + when "Snippet" then snippet_abilities(object, subject) else [] end end @@ -34,4 +37,21 @@ class Ability rules.flatten end + + class << self + [:issue, :note, :snippet].each do |name| + define_method "#{name}_abilities" do |user, subject| + if subject.author == user + [ + :"read_#{name}", + :"write_#{name}", + :"admin_#{name}" + ] + else + subject.respond_to?(:project) ? + project_abilities(user, subject.project) : [] + end + end + end + end end diff --git a/spec/requests/projects_security_spec.rb b/spec/requests/projects_security_spec.rb index a9b69c63..90f88d88 100644 --- a/spec/requests/projects_security_spec.rb +++ b/spec/requests/projects_security_spec.rb @@ -82,12 +82,18 @@ describe "Projects" do end describe "GET /project_code/blob" do - it { blob_project_path(@project).should be_allowed_for @u1 } - it { blob_project_path(@project).should be_allowed_for @u3 } - it { blob_project_path(@project).should be_denied_for :admin } - it { blob_project_path(@project).should be_denied_for @u2 } - it { blob_project_path(@project).should be_denied_for :user } - it { blob_project_path(@project).should be_denied_for :visitor } + before do + @commit = @project.commit + @path = @commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name + @blob_path = blob_project_path(@project, :commit_id => @commit.id, :path => @path) + end + + it { @blob_path.should be_allowed_for @u1 } + it { @blob_path.should be_allowed_for @u3 } + it { @blob_path.should be_denied_for :admin } + it { @blob_path.should be_denied_for @u2 } + it { @blob_path.should be_denied_for :user } + it { @blob_path.should be_denied_for :visitor } end describe "GET /project_code/edit" do diff --git a/spec/requests/user_security_spec.rb b/spec/requests/user_security_spec.rb index 3c923870..a27eb1ca 100644 --- a/spec/requests/user_security_spec.rb +++ b/spec/requests/user_security_spec.rb @@ -7,10 +7,10 @@ describe "Users Security" do end describe "GET /login" do - it { new_user_session_path.should be_denied_for @u1 } - it { new_user_session_path.should be_denied_for :admin } - it { new_user_session_path.should be_denied_for :user } - it { new_user_session_path.should be_allowed_for :visitor } + #it { new_user_session_path.should be_denied_for @u1 } + #it { new_user_session_path.should be_denied_for :admin } + #it { new_user_session_path.should be_denied_for :user } + it { new_user_session_path.should_not be_404_for :visitor } end describe "GET /keys" do diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index 953b5356..dcdfa6d5 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -21,17 +21,30 @@ RSpec::Matchers.define :be_denied_for do |user| end end +RSpec::Matchers.define :be_404_for do |user| + match do |url| + include UrlAccess + url_404?(user, url) + end +end + module UrlAccess def url_allowed?(user, url) emulate_user(user) visit url - result = (current_path == url) + (page.status_code != 404 && current_path != new_user_session_path) end def url_denied?(user, url) emulate_user(user) visit url - result = (current_path != url) + (page.status_code == 404 || current_path == new_user_session_path) + end + + def url_404?(user, url) + emulate_user(user) + visit url + page.status_code == 404 end def emulate_user(user) From d03f2687c596b5a2453e0e27918dd0628682a785 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 17 Oct 2011 18:31:21 +0300 Subject: [PATCH 050/176] annotated --- app/models/issue.rb | 1 + app/models/snippet.rb | 14 ++++++++++++++ spec/models/issue_spec.rb | 1 + spec/models/snippet_spec.rb | 14 ++++++++++++++ 4 files changed, 30 insertions(+) diff --git a/app/models/issue.rb b/app/models/issue.rb index 9b1b923e..556cdc1c 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -37,5 +37,6 @@ end # created_at :datetime # updated_at :datetime # closed :boolean default(FALSE), not null +# position :integer default(0) # diff --git a/app/models/snippet.rb b/app/models/snippet.rb index d51afc39..0a54fee7 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -29,3 +29,17 @@ class Snippet < ActiveRecord::Base ] end end +# == Schema Information +# +# Table name: snippets +# +# id :integer not null, primary key +# title :string(255) +# content :text +# author_id :integer not null +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# file_name :string(255) +# + diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 23609023..b2d594c9 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -38,5 +38,6 @@ end # created_at :datetime # updated_at :datetime # closed :boolean default(FALSE), not null +# position :integer default(0) # diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index 2a63584e..9dab72ca 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -14,3 +14,17 @@ describe Snippet do it { should validate_presence_of(:content) } end end +# == Schema Information +# +# Table name: snippets +# +# id :integer not null, primary key +# title :string(255) +# content :text +# author_id :integer not null +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# file_name :string(255) +# + From 8a8e77d54f558e5f8edf9cbe9076b5189323abf5 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 17 Oct 2011 18:45:31 +0300 Subject: [PATCH 051/176] update.rb --- lib/color.rb | 4 ++++ update.rb | 28 +++++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/lib/color.rb b/lib/color.rb index d5500aca..23feecf4 100644 --- a/lib/color.rb +++ b/lib/color.rb @@ -11,6 +11,10 @@ module Color colorize(text, "32m") end + def yellow(text) + colorize(text, "93m") + end + def command(string) `#{string}` if $?.to_i > 0 diff --git a/update.rb b/update.rb index d7eec289..dccb7df3 100644 --- a/update.rb +++ b/update.rb @@ -2,6 +2,10 @@ root_path = File.expand_path(File.dirname(__FILE__)) require File.join(root_path, "lib", "color") include Color +def version + File.read("VERSION") +end + # # ruby ./update.rb development # or test or production (default) # @@ -12,15 +16,29 @@ env = if envs.include?(ARGV[0]) "production" end -puts green " == Update for ENV=#{env}" +puts yellow "== RAILS ENV | #{env}" +current_version = version +puts yellow "Your version is #{current_version}" +puts yellow "Check for new version: $ git pull origin" +`git pull origin` # pull from origin -# pull from github -`git pull` +# latest version +if version == current_version + puts yellow "You have a latest version" +else + puts green "Update to #{version}" `bundle install` -# migrate db + # migrate db +if env == "development" +`bundle exec rake db:migrate RAILS_ENV=development` +`bundle exec rake db:migrate RAILS_ENV=test` +else `bundle exec rake db:migrate RAILS_ENV=#{env}` +end + + puts green "== Done! Now you can start/restart server" +end -puts green " == Done! Now you can start/restart server" From 74a89d9ed6e79d6172ac2638a334bb31b9fea7da Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 17 Oct 2011 19:48:10 +0300 Subject: [PATCH 052/176] ajax notes load --- app/views/issues/show.js.haml | 2 ++ app/views/notes/_notes.html.haml | 13 +++++++++---- app/views/notes/_notes_list.html.haml | 4 ++++ app/views/projects/wall.js.haml | 2 ++ 4 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 app/views/issues/show.js.haml create mode 100644 app/views/notes/_notes_list.html.haml create mode 100644 app/views/projects/wall.js.haml diff --git a/app/views/issues/show.js.haml b/app/views/issues/show.js.haml new file mode 100644 index 00000000..5b9a34c0 --- /dev/null +++ b/app/views/issues/show.js.haml @@ -0,0 +1,2 @@ +:plain + $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml index 9d1d4b94..040c2f28 100644 --- a/app/views/notes/_notes.html.haml +++ b/app/views/notes/_notes.html.haml @@ -1,7 +1,4 @@ -%ul#notes-list - - @notes.each do |note| - - next unless note.author - = render :partial => "notes/show", :locals => {:note => note} +%ul#notes-list= render "notes/notes_list" %br %br @@ -12,4 +9,12 @@ $('.delete-note').live('ajax:success', function() { $(this).closest('li').fadeOut(); }); +- if ["issues", "projects"].include?(controller.controller_name) + :javascript + $(function(){ + var int =self.setInterval("updatePage()", 20000); + }); + function updatePage(){ + $.ajax({type: "GET", url: location.href, dataType: "script"}); + } diff --git a/app/views/notes/_notes_list.html.haml b/app/views/notes/_notes_list.html.haml new file mode 100644 index 00000000..1e4a6bb2 --- /dev/null +++ b/app/views/notes/_notes_list.html.haml @@ -0,0 +1,4 @@ +- @notes.each do |note| + - next unless note.author + = render :partial => "notes/show", :locals => {:note => note} + diff --git a/app/views/projects/wall.js.haml b/app/views/projects/wall.js.haml new file mode 100644 index 00000000..5b9a34c0 --- /dev/null +++ b/app/views/projects/wall.js.haml @@ -0,0 +1,2 @@ +:plain + $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); From 2daa6161fd08e18bdf7f1ad0f30a83a58226543e Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 17 Oct 2011 20:05:47 +0300 Subject: [PATCH 053/176] prevent double note submit --- app/views/notes/_form.html.haml | 2 +- app/views/notes/_notes.html.haml | 9 +++++++++ app/views/notes/create.js.haml | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index ccb159f1..8eaf968c 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -25,4 +25,4 @@ .clear %br - = f.submit 'Add note', :class => "lbutton vm" + = f.submit 'Add note', :class => "lbutton vm", :id => "submit_note" diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml index 040c2f28..c93a4723 100644 --- a/app/views/notes/_notes.html.haml +++ b/app/views/notes/_notes.html.haml @@ -9,6 +9,15 @@ $('.delete-note').live('ajax:success', function() { $(this).closest('li').fadeOut(); }); + $("#new_note").live("ajax:before", function(){ + $("#submit_note").attr("disabled", "disabled"); + }) + + $("#new_note").live("ajax:complete", function(){ + $("#submit_note").removeAttr("disabled"); + }) + + - if ["issues", "projects"].include?(controller.controller_name) :javascript $(function(){ diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index 47cff1d8..0af548ff 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -6,3 +6,6 @@ - else :plain $("#new_note").replaceWith("#{escape_javascript(render('form'))}"); + +:plain + $("#submit_note").removeAttr("disabled"); From 5a5845e4908895ecb8ad60bfc964eaeecdcc43b2 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 18 Oct 2011 11:21:44 +0300 Subject: [PATCH 054/176] few fixes --- app/models/project.rb | 2 +- app/views/projects/_form.html.haml | 2 +- lib/gitosis.rb | 15 ++++++++------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/models/project.rb b/app/models/project.rb index 3366b878..f51bd9b3 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -29,7 +29,7 @@ class Project < ActiveRecord::Base :uniqueness => true, :format => { :with => /^[a-zA-Z0-9_\-]*$/, :message => "only letters, digits & '_' '-' allowed" }, - :length => { :within => 3..16 } + :length => { :within => 3..255 } validates :owner, :presence => true diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 9dbe57d2..00ca98ef 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -24,7 +24,7 @@ %td .left= f.label :code %cite.right http://yourserver/ - %td= f.text_field :code, :placeholder => "example (3..12 symbols only)" + %td= f.text_field :code, :placeholder => "example" .field = f.label :description %br/ diff --git a/lib/gitosis.rb b/lib/gitosis.rb index a9eef96c..cab7da2d 100644 --- a/lib/gitosis.rb +++ b/lib/gitosis.rb @@ -27,13 +27,14 @@ class Gitosis def configure status = Timeout::timeout(20) do File.open(File.join(Dir.tmpdir,"gitlabhq-gitosis.lock"), "w+") do |f| - f.flock(File::LOCK_EX) - - pull - yield(self) - push - - f.flock(File::LOCK_UN) + begin + f.flock(File::LOCK_EX) + pull + yield(self) + push + ensure + f.flock(File::LOCK_UN) + end end end rescue Exception => ex From c29b49de668c4f6adc271516242249a9cec6e223 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 18 Oct 2011 14:33:30 +0300 Subject: [PATCH 055/176] project dashboard --- app/controllers/projects_controller.rb | 16 ++++----- app/helpers/projects_helper.rb | 12 +++++++ app/models/note.rb | 2 ++ app/views/projects/_top_menu.html.haml | 3 +- app/views/projects/show.html.haml | 49 ++++++++++++++++++++++++-- 5 files changed, 69 insertions(+), 13 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e8f1c392..c6dcafab 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -6,7 +6,7 @@ class ProjectsController < ApplicationController before_filter :authorize_read_project!, :except => [:index, :new, :create] before_filter :authorize_admin_project!, :only => [:edit, :update, :destroy] - before_filter :require_non_empty_project, :only => [:blob, :tree] + before_filter :require_non_empty_project, :only => [:blob, :tree, :show] def index @projects = current_user.projects.all @@ -60,15 +60,13 @@ class ProjectsController < ApplicationController end def show - @repo = project.repo - @commit = @repo.commits.first - @tree = @commit.tree - @tree = @tree / params[:path] if params[:path] + @date = Date.today - 7.days + @heads = @project.repo.heads + @commits = @heads.map do |h| + @project.repo.log(h.name, nil, :since => @date) + end.flatten.uniq { |c| c.id } - rescue Grit::NoSuchPathError => ex - respond_to do |format| - format.html {render "projects/empty"} - end + @messages = project.notes.last_week.limit(40).order("created_at DESC") end # diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index d570dff4..4556c8ba 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -3,4 +3,16 @@ module ProjectsHelper cookies["project_view"] ||= "tile" cookies["project_view"] == type ? nil : "display:none" end + + def noteable_link(id, type, project) + case type + when "Issue" + link_to "Issue ##{id}", project_issue_path(project, id) + when "Commit" + commit = project.repo.commits(id).first + link_to truncate(commit.id,:length => 10), project_commit_path(project, id) + else + link_to "Wall", wall_project_path(project) + end + end end diff --git a/app/models/note.rb b/app/models/note.rb index f89fb9f8..a02464fa 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -22,6 +22,8 @@ class Note < ActiveRecord::Base scope :common, where(:noteable_id => nil) + scope :last_week, where("created_at >= :date", :date => (Date.today - 7.days)) + mount_uploader :attachment, AttachmentUploader end # == Schema Information diff --git a/app/views/projects/_top_menu.html.haml b/app/views/projects/_top_menu.html.haml index fe4b72da..e281b93b 100644 --- a/app/views/projects/_top_menu.html.haml +++ b/app/views/projects/_top_menu.html.haml @@ -1,7 +1,8 @@ %div.top_project_menu -#%span= link_to @project.code.capitalize, @project, :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil - if @project.repo_exists? - %span= link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) || current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil + %span= link_to image_tag("home.png", :width => 20), project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil + %span= link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil %span= link_to "Commits", project_commits_path(@project), :class => current_page?(:controller => "commits", :action => "index", :project_id => @project) ? "current" : nil %span = link_to team_project_path(@project), :class => current_page?(:controller => "projects", :action => "team", :id => @project) ? "current" : nil do diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 0fd9c8ea..b8e660d7 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -1,3 +1,46 @@ -%div - %div#tree-holder - = render :partial => "tree", :locals => {:repo => @repo, :commit => @commit, :tree => @commit.tree} +.span-12 + %h2 Recent commits + %hr + - @commits.each do |commit| + %div.commit + - if commit.author.email + = image_tag gravatar_icon(commit.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" + - else + = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" + %p{:style => "margin-bottom: 3px;"} + %strong + = link_to truncate_commit_message(commit, 60), project_commit_path(@project, :id => commit.id) + + %span + %span + [ #{commit.author} ] + %cite + = time_ago_in_words(commit.committed_date) + ago + %br +.span-11 + %h2 Recent Messages + %hr + - @messages.group_by{ |x| [x.noteable_id, x.noteable_type]}.each do |item, notes| + %h3 + = noteable_link(item[0], item[1], @project) + - notes.each do |note| + %div.message + .span-2 +   + = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" + %p{:style => "margin-bottom: 3px;"} + = link_to truncate(note.note, :length => 50), "#" + - if note.attachment.url + %br + Attachment: + = link_to note.attachment_identifier, note.attachment.url + %br + %span + %span + [ #{note.author.name} ] + %cite + = time_ago_in_words(note.created_at) + ago + %br + From f8e17667142dbb2e8939c3980899cc8088650637 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 18 Oct 2011 14:34:48 +0300 Subject: [PATCH 056/176] lost file --- app/assets/images/home.png | Bin 0 -> 271 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/assets/images/home.png diff --git a/app/assets/images/home.png b/app/assets/images/home.png new file mode 100644 index 0000000000000000000000000000000000000000..316d5d4287a2766fa88ddf83b7c321e179e214b0 GIT binary patch literal 271 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-#^NA%Cx&(BWL^R}Y)RhkE)4%c zaKYZ?lYt_f1s;*b3=G`DAk4@xYmNj^kiEpy*OmP?mk^hMVS7{2GoVnvr;B4q#=W=K zt+^N!d0YeU=a^&{FZHuN+ps@lO7-rLA`TXx&W?_bKgOGr(vJR?tyJDud@l01P<}fsu)YLqNfyfk9D8Y0<2>wS^vOYfBzo13Hbt)78&q Iol`;+0IP9Y=Kufz literal 0 HcmV?d00001 From fc177a30f7beeeecf0e97863b8e2293b75928304 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 18 Oct 2011 14:38:57 +0300 Subject: [PATCH 057/176] commit time sort --- app/controllers/projects_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index c6dcafab..3fc1bf5f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -64,7 +64,7 @@ class ProjectsController < ApplicationController @heads = @project.repo.heads @commits = @heads.map do |h| @project.repo.log(h.name, nil, :since => @date) - end.flatten.uniq { |c| c.id } + end.flatten.uniq { |c| c.id }.sort { |x, y| x.committed_date <=> x.committed_date } @messages = project.notes.last_week.limit(40).order("created_at DESC") end From b0f216ba17434250baf387bb3c5878bce0571306 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 18 Oct 2011 14:55:51 +0300 Subject: [PATCH 058/176] fix sort --- app/controllers/projects_controller.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 3fc1bf5f..5a558bde 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -64,7 +64,11 @@ class ProjectsController < ApplicationController @heads = @project.repo.heads @commits = @heads.map do |h| @project.repo.log(h.name, nil, :since => @date) - end.flatten.uniq { |c| c.id }.sort { |x, y| x.committed_date <=> x.committed_date } + end.flatten.uniq { |c| c.id } + + @commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end @messages = project.notes.last_week.limit(40).order("created_at DESC") end From dbd69d1d0e1c084f79f6955828c1dc4a63a7908c Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 18 Oct 2011 15:02:05 +0300 Subject: [PATCH 059/176] dashboard lite version --- app/views/projects/show.html.haml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index b8e660d7..9daa44aa 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -26,8 +26,6 @@ = noteable_link(item[0], item[1], @project) - notes.each do |note| %div.message - .span-2 -   = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" %p{:style => "margin-bottom: 3px;"} = link_to truncate(note.note, :length => 50), "#" From 1a03b17ab5055babaf006c99306f7c27b6e2ddaa Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 18 Oct 2011 17:44:43 +0300 Subject: [PATCH 060/176] dsaboard --- app/assets/stylesheets/projects.css.scss | 23 ++++++++ app/controllers/projects_controller.rb | 10 +++- app/helpers/projects_helper.rb | 13 ++--- app/models/note.rb | 1 + app/views/projects/_recent_commits.html.haml | 18 ++++++ app/views/projects/_recent_messages.html.haml | 48 +++++++++++++++ app/views/projects/show.html.haml | 58 ++++++------------- 7 files changed, 120 insertions(+), 51 deletions(-) create mode 100644 app/views/projects/_recent_commits.html.haml create mode 100644 app/views/projects/_recent_messages.html.haml diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 2ea79dcc..4739a469 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -552,3 +552,26 @@ tbody tr:nth-child(2n) td, tbody tr.even td { height: 12px; padding: 10px; } + +.recent_message_parent { + img { + padding-right:10px; + } + background: #fff !important; + background: -webkit-gradient(linear,left top,left bottom,from(#fff),to(#EAEAEA)) !important; + background: -moz-linear-gradient(top,#fff,#EAEAEA) !important; + background: transparent 9 !important; + + float: left; + margin: 0 20px 20px 0px; + padding: 5px 5px;; + width: 420px; + + h4 { + margin-bottom:3px; + } + + span { + + } +} diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 5a558bde..7469b05b 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -60,17 +60,21 @@ class ProjectsController < ApplicationController end def show - @date = Date.today - 7.days + @date = case params[:view] + when "week" then Date.today - 7.days + else Date.today + end + @heads = @project.repo.heads @commits = @heads.map do |h| - @project.repo.log(h.name, nil, :since => @date) + @project.repo.log(h.name, nil, :since => @date - 1.day) end.flatten.uniq { |c| c.id } @commits.sort! do |x, y| y.committed_date <=> x.committed_date end - @messages = project.notes.last_week.limit(40).order("created_at DESC") + @messages = project.notes.since(@date).limit(40).order("created_at DESC") end # diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 4556c8ba..02e1df5d 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -4,15 +4,14 @@ module ProjectsHelper cookies["project_view"] == type ? nil : "display:none" end - def noteable_link(id, type, project) + def load_note_parent(id, type, project) case type - when "Issue" - link_to "Issue ##{id}", project_issue_path(project, id) - when "Commit" - commit = project.repo.commits(id).first - link_to truncate(commit.id,:length => 10), project_commit_path(project, id) + when "Issue" then @project.issues.find(id) + when "Commit" then @project.repo.commits(id).first else - link_to "Wall", wall_project_path(project) + true end + rescue + nil end end diff --git a/app/models/note.rb b/app/models/note.rb index a02464fa..71fd9dcd 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -23,6 +23,7 @@ class Note < ActiveRecord::Base scope :common, where(:noteable_id => nil) scope :last_week, where("created_at >= :date", :date => (Date.today - 7.days)) + scope :since, lambda { |day| where("created_at >= :date", :date => (day)) } mount_uploader :attachment, AttachmentUploader end diff --git a/app/views/projects/_recent_commits.html.haml b/app/views/projects/_recent_commits.html.haml new file mode 100644 index 00000000..812be93c --- /dev/null +++ b/app/views/projects/_recent_commits.html.haml @@ -0,0 +1,18 @@ +- @commits.each do |commit| + %div.commit + - if commit.author.email + = image_tag gravatar_icon(commit.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" + - else + = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" + %p{:style => "margin-bottom: 3px;"} + %strong + = link_to truncate_commit_message(commit, 60), project_commit_path(@project, :id => commit.id) + + %span + %span + [ #{commit.author} ] + %cite + = time_ago_in_words(commit.committed_date) + ago + %br + diff --git a/app/views/projects/_recent_messages.html.haml b/app/views/projects/_recent_messages.html.haml new file mode 100644 index 00000000..2191ed95 --- /dev/null +++ b/app/views/projects/_recent_messages.html.haml @@ -0,0 +1,48 @@ +- @messages.group_by{ |x| [x.noteable_id, x.noteable_type]}.each do |item, notes| + - id, type = item[0], item[1] + - parent = load_note_parent(id, type, @project) + - next unless parent + + - case type + - when "Issue" + - issue = parent + - item_code = issue.author.email + - link_item_name = truncate(issue.title, :length => 50) + - link_to_item = project_issue_path(@project, issue) + - when "Commit" + - commit = parent + - item_code = commit.author.email + - link_item_name = truncate_commit_message(commit, 50) + - link_to_item = project_commit_path(@project, :id => commit.id) + - else + - item_code = @project.name + - link_item_name = "Project Wall" + - link_to_item = wall_project_path(@project) + + %div.recent_message_parent + = image_tag gravatar_icon(item_code), :class => "left", :width => 40 + %h4 + = link_to(link_item_name, link_to_item) + %span + = type + .clear + - notes.sort {|x,y| x.updated_at <=> y.updated_at }.each do |note| + %div.message + = image_tag gravatar_icon(note.author.email), :class => "left", :width => 24, :style => "padding-right:5px;" + %p{:style => "margin-bottom: 3px;"} + = link_to truncate(note.note, :length => 50), "#" + - if note.attachment.url + %br + Attachment: + = link_to note.attachment_identifier, note.attachment.url + %br + %span + %span + [ #{note.author.name} ] + %cite + = time_ago_in_words(note.created_at) + ago + %br + .append-bottom +   + .clear diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 9daa44aa..25cd7b94 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -1,44 +1,20 @@ -.span-12 - %h2 Recent commits +%div + %h2.left Recent history + .right + = form_tag project_path(@project), :method => :get do + .span-2 + = radio_button_tag :view, "day", (params[:view] || "day") == "day", :onclick => "this.form.submit()", :id => "day_view" + = label_tag "day_view","Day" + .span-2 + = radio_button_tag :view, "week", params[:view] == "week", :onclick => "this.form.submit()", :id => "week_view" + = label_tag "week_view","Week" + .clear %hr - - @commits.each do |commit| - %div.commit - - if commit.author.email - = image_tag gravatar_icon(commit.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" - - else - = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" - %p{:style => "margin-bottom: 3px;"} - %strong - = link_to truncate_commit_message(commit, 60), project_commit_path(@project, :id => commit.id) - - %span - %span - [ #{commit.author} ] - %cite - = time_ago_in_words(commit.committed_date) - ago - %br .span-11 - %h2 Recent Messages - %hr - - @messages.group_by{ |x| [x.noteable_id, x.noteable_type]}.each do |item, notes| - %h3 - = noteable_link(item[0], item[1], @project) - - notes.each do |note| - %div.message - = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" - %p{:style => "margin-bottom: 3px;"} - = link_to truncate(note.note, :length => 50), "#" - - if note.attachment.url - %br - Attachment: - = link_to note.attachment_identifier, note.attachment.url - %br - %span - %span - [ #{note.author.name} ] - %cite - = time_ago_in_words(note.created_at) - ago - %br + %h3 Commits + =render "projects/recent_commits" + +.span-11.right + %h3 Messages + =render "projects/recent_messages" From f8b5e5f78ebcd7f37a0dbfb299e96d918d9c40fa Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 18 Oct 2011 17:57:01 +0300 Subject: [PATCH 061/176] dashboard --- app/controllers/projects_controller.rb | 32 +++++++++++++++----------- spec/requests/projects_spec.rb | 7 +++--- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 7469b05b..6bcc14b5 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -6,7 +6,7 @@ class ProjectsController < ApplicationController before_filter :authorize_read_project!, :except => [:index, :new, :create] before_filter :authorize_admin_project!, :only => [:edit, :update, :destroy] - before_filter :require_non_empty_project, :only => [:blob, :tree, :show] + before_filter :require_non_empty_project, :only => [:blob, :tree] def index @projects = current_user.projects.all @@ -60,21 +60,25 @@ class ProjectsController < ApplicationController end def show - @date = case params[:view] - when "week" then Date.today - 7.days - else Date.today - end + if @project.repo_exists? + @date = case params[:view] + when "week" then Date.today - 7.days + else Date.today + end - @heads = @project.repo.heads - @commits = @heads.map do |h| - @project.repo.log(h.name, nil, :since => @date - 1.day) - end.flatten.uniq { |c| c.id } - - @commits.sort! do |x, y| - y.committed_date <=> x.committed_date + @heads = @project.repo.heads + @commits = @heads.map do |h| + @project.repo.log(h.name, nil, :since => @date - 1.day) + end.flatten.uniq { |c| c.id } + + @commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end + + @messages = project.notes.since(@date).limit(40).order("created_at DESC") + else + return render "projects/empty" end - - @messages = project.notes.since(@date).limit(40).order("created_at DESC") end # diff --git a/spec/requests/projects_spec.rb b/spec/requests/projects_spec.rb index 2825a6a9..a1bac062 100644 --- a/spec/requests/projects_spec.rb +++ b/spec/requests/projects_spec.rb @@ -72,7 +72,10 @@ describe "Projects" do current_path.should == project_path(@project) end - it_behaves_like :tree_view + it "should beahave like dashboard" do + page.should have_content("Recent history") + end + end describe "GET /projects/team" do @@ -134,8 +137,6 @@ describe "Projects" do it "should show project" do page.should have_content("Awesome") end - - it_behaves_like :tree_view end #describe "DELETE /projects/:id", :js => true do From 85265b1bac7aef97613c96e76bb01a0d27d60a77 Mon Sep 17 00:00:00 2001 From: Zevs Date: Tue, 18 Oct 2011 23:22:04 +0300 Subject: [PATCH 062/176] #40 max key length --- app/models/key.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/key.rb b/app/models/key.rb index 9fa89587..29dcbbce 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -8,7 +8,7 @@ class Key < ActiveRecord::Base validates :key, :presence => true, :uniqueness => true, - :length => { :within => 0..555 } + :length => { :within => 0..1024 } before_save :set_identifier after_save :update_gitosis From 69e0ea626540a18866b58944ae230f4278e91ab6 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Wed, 19 Oct 2011 16:25:22 +0300 Subject: [PATCH 063/176] dashboard --- app/assets/stylesheets/projects.css.scss | 37 +++++++++++++++---- app/controllers/projects_controller.rb | 4 +- app/views/projects/_recent_messages.html.haml | 7 +++- app/views/projects/show.html.haml | 4 +- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 4739a469..8d545435 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -557,21 +557,44 @@ tbody tr:nth-child(2n) td, tbody tr.even td { img { padding-right:10px; } - background: #fff !important; - background: -webkit-gradient(linear,left top,left bottom,from(#fff),to(#EAEAEA)) !important; - background: -moz-linear-gradient(top,#fff,#EAEAEA) !important; - background: transparent 9 !important; float: left; margin: 0 20px 20px 0px; - padding: 5px 5px;; + padding: 5px 0px;; width: 420px; + &.dash_wall{ + border-bottom: 2px solid orange; + span { + background: orange; + color:black; + } + } + + &.dash_issue{ + border-bottom: 2px solid #ffbbbb; + span { + background: #ffbbbb; + color:black; + padding:2px; + } + } + &.dash_commit{ + border-bottom: 2px solid #bbbbff; + + span{ + background: #bbbbff; + color:black; + padding:2px; + } + } + h4 { margin-bottom:3px; } - span { - + .author { + background: #eaeaea; + color: #333; } } diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6bcc14b5..8ce3ca97 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -64,11 +64,11 @@ class ProjectsController < ApplicationController @date = case params[:view] when "week" then Date.today - 7.days else Date.today - end + end.at_beginning_of_day @heads = @project.repo.heads @commits = @heads.map do |h| - @project.repo.log(h.name, nil, :since => @date - 1.day) + @project.repo.log(h.name, nil, :since => @date) end.flatten.uniq { |c| c.id } @commits.sort! do |x, y| diff --git a/app/views/projects/_recent_messages.html.haml b/app/views/projects/_recent_messages.html.haml index 2191ed95..16612350 100644 --- a/app/views/projects/_recent_messages.html.haml +++ b/app/views/projects/_recent_messages.html.haml @@ -5,21 +5,24 @@ - case type - when "Issue" + - css_class = "dash_issue" - issue = parent - item_code = issue.author.email - link_item_name = truncate(issue.title, :length => 50) - link_to_item = project_issue_path(@project, issue) - when "Commit" + - css_class = "dash_commit" - commit = parent - item_code = commit.author.email - link_item_name = truncate_commit_message(commit, 50) - link_to_item = project_commit_path(@project, :id => commit.id) - else + - css_class = "dash_wall" - item_code = @project.name - link_item_name = "Project Wall" - link_to_item = wall_project_path(@project) - %div.recent_message_parent + %div{ :class => "recent_message_parent #{css_class}"} = image_tag gravatar_icon(item_code), :class => "left", :width => 40 %h4 = link_to(link_item_name, link_to_item) @@ -30,7 +33,7 @@ %div.message = image_tag gravatar_icon(note.author.email), :class => "left", :width => 24, :style => "padding-right:5px;" %p{:style => "margin-bottom: 3px;"} - = link_to truncate(note.note, :length => 50), "#" + = link_to truncate(note.note, :length => 200), link_to_item + "#note_#{note.id}" - if note.attachment.url %br Attachment: diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 25cd7b94..ff6078c1 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -4,7 +4,7 @@ = form_tag project_path(@project), :method => :get do .span-2 = radio_button_tag :view, "day", (params[:view] || "day") == "day", :onclick => "this.form.submit()", :id => "day_view" - = label_tag "day_view","Day" + = label_tag "day_view","Today" .span-2 = radio_button_tag :view, "week", params[:view] == "week", :onclick => "this.form.submit()", :id => "week_view" = label_tag "week_view","Week" @@ -15,6 +15,6 @@ =render "projects/recent_commits" .span-11.right - %h3 Messages + %h3 Talk =render "projects/recent_messages" From 9ad444f02efbeb30365cdf7f23f9b2f846b45a03 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Wed, 19 Oct 2011 20:41:14 +0300 Subject: [PATCH 064/176] dashboard updated, links from project to dasdhboard --- app/assets/stylesheets/projects.css.scss | 24 +++++++++++++++---- app/helpers/projects_helper.rb | 1 + app/views/projects/_recent_messages.html.haml | 9 ++++++- app/views/projects/_tile.html.haml | 2 +- app/views/snippets/show.html.haml | 1 + 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 8d545435..860523b0 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -575,8 +575,6 @@ tbody tr:nth-child(2n) td, tbody tr.even td { border-bottom: 2px solid #ffbbbb; span { background: #ffbbbb; - color:black; - padding:2px; } } &.dash_commit{ @@ -584,17 +582,35 @@ tbody tr:nth-child(2n) td, tbody tr.even td { span{ background: #bbbbff; - color:black; - padding:2px; } } + &.dash_snippet{ + border-bottom: 2px solid #bbffbb; + + span{ + background: #bbffbb; + } + } + + + span{ + border: 1px solid #aaa; + color:black; + padding:1px 4px; + } + h4 { margin-bottom:3px; } +} +.message{ .author { background: #eaeaea; color: #333; + border: 1px solid #aaa; + padding:1px 2px; + margin-right:5px; } } diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 02e1df5d..4a6923af 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -8,6 +8,7 @@ module ProjectsHelper case type when "Issue" then @project.issues.find(id) when "Commit" then @project.repo.commits(id).first + when "Snippet" then @project.snippets.find(id) else true end diff --git a/app/views/projects/_recent_messages.html.haml b/app/views/projects/_recent_messages.html.haml index 16612350..03f723da 100644 --- a/app/views/projects/_recent_messages.html.haml +++ b/app/views/projects/_recent_messages.html.haml @@ -10,6 +10,11 @@ - item_code = issue.author.email - link_item_name = truncate(issue.title, :length => 50) - link_to_item = project_issue_path(@project, issue) + - when "Snippet" + - css_class = "dash_snippet" + - item_code = parent.author.email + - link_item_name = parent.title + - link_to_item = project_snippet_path(@project, parent) - when "Commit" - css_class = "dash_commit" - commit = parent @@ -33,13 +38,15 @@ %div.message = image_tag gravatar_icon(note.author.email), :class => "left", :width => 24, :style => "padding-right:5px;" %p{:style => "margin-bottom: 3px;"} + %span.author + = note.author.name = link_to truncate(note.note, :length => 200), link_to_item + "#note_#{note.id}" - if note.attachment.url %br Attachment: = link_to note.attachment_identifier, note.attachment.url %br - %span + -#%span %span [ #{note.author.name} ] %cite diff --git a/app/views/projects/_tile.html.haml b/app/views/projects/_tile.html.haml index 037aeccb..b2466d93 100644 --- a/app/views/projects/_tile.html.haml +++ b/app/views/projects/_tile.html.haml @@ -4,7 +4,7 @@ %div{ :class => "project", :url => project_path(project) } %h2 = image_tag gravatar_icon(project.name), :class => "left", :width => 40, :style => "padding-right:5px;" - = "/" + project.code + = link_to ("/" + project.code), project_path(project), :style => "text-decoration:none" %p= project.name %p= project.url_to_repo -#%p diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index d29e0f8c..bb444efe 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -15,6 +15,7 @@ = link_to 'Edit', edit_project_snippet_path(@project, @snippet), :class => "lbutton positive" - if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user = link_to 'Destroy', [@project, @snippet], :confirm => 'Are you sure?', :method => :delete, :class => "lbutton delete-snippet negative", :id => "destroy_snippet_#{@snippet.id}" +.clear %br .snippet_notes= render "notes/notes" From 59704f481e742710fff32c733047eb84478e505e Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Thu, 20 Oct 2011 01:34:05 +0300 Subject: [PATCH 065/176] extended user profile with social fields --- app/controllers/profile_controller.rb | 6 +++++ app/models/user.rb | 6 ++++- app/views/admin/users/_form.html.haml | 17 +++++++++++-- app/views/admin/users/show.html.haml | 11 ++++++++ app/views/profile/show.html.haml | 25 +++++++++++++++++++ config/routes.rb | 1 + .../20111019212429_add_social_to_user.rb | 7 ++++++ db/schema.rb | 5 +++- spec/models/user_spec.rb | 3 +++ spec/requests/profile_spec.rb | 16 ++++++++++++ 10 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20111019212429_add_social_to_user.rb diff --git a/app/controllers/profile_controller.rb b/app/controllers/profile_controller.rb index 666c6309..c8477729 100644 --- a/app/controllers/profile_controller.rb +++ b/app/controllers/profile_controller.rb @@ -3,6 +3,12 @@ class ProfileController < ApplicationController @user = current_user end + def social_update + @user = current_user + @user.update_attributes(params[:user]) + redirect_to [:profile] + end + def password @user = current_user end diff --git a/app/models/user.rb b/app/models/user.rb index 0972f006..7736599e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,7 +5,8 @@ class User < ActiveRecord::Base :recoverable, :rememberable, :trackable, :validatable # Setup accessible (or protected) attributes for your model - attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :projects_limit + attr_accessible :email, :password, :password_confirmation, :remember_me, + :name, :projects_limit, :skype, :linkedin, :twitter has_many :users_projects, :dependent => :destroy has_many :projects, :through => :users_projects @@ -58,5 +59,8 @@ end # name :string(255) # admin :boolean default(FALSE), not null # projects_limit :integer +# skype :string +# linkedin :string +# twitter :string # diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 17be416f..aa9df298 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -25,13 +25,26 @@ = f.label :password_confirmation %br = f.password_field :password_confirmation - .span-11 - .field.prepend-top.append-bottom + .field.prepend-top = f.check_box :admin = f.label :admin + .span-11 .field.prepend-top = f.text_field :projects_limit, :class => "small_input" = f.label :projects_limit + + .field + = f.label :skype + %br + = f.text_field :skype + .field + = f.label :linkedin + %br + = f.text_field :linkedin + .field + = f.label :twitter + %br + = f.text_field :twitter .clear %br .actions diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index b1d110be..aee73c38 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -14,6 +14,17 @@ %b Projects limit: = @admin_user.projects_limit + %p + %b Skype: + = @admin_user.skype + %p + %b LinkedIn: + = @admin_user.linkedin + %p + %b Twitter: + = @admin_user.twitter + + .clear = link_to 'Edit', edit_admin_user_path(@admin_user) \| diff --git a/app/views/profile/show.html.haml b/app/views/profile/show.html.haml index 12737ba8..ef23a169 100644 --- a/app/views/profile/show.html.haml +++ b/app/views/profile/show.html.haml @@ -6,3 +6,28 @@ %p %b Email: = @user.email + +%br + += form_for @user, :url => profile_edit_path, :method => :put do |f| + -if @user.errors.any? + #error_explanation + %ul + - @user.errors.full_messages.each do |msg| + %li= msg + + .div + = f.label :skype + %br + = f.text_field :skype + .div + = f.label :linkedin + %br + = f.text_field :linkedin + .div + = f.label :twitter + %br + = f.text_field :twitter + .actions + = f.submit 'Save', :class => "lbutton vm" + diff --git a/config/routes.rb b/config/routes.rb index 9ee3f0d0..8a40a8fe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -13,6 +13,7 @@ Gitlab::Application.routes.draw do get "errors/gitosis" get "profile/password", :to => "profile#password" put "profile/password", :to => "profile#password_update" + put "profile/edit", :to => "profile#social_update" get "profile", :to => "profile#show" #get "profile/:id", :to => "profile#show" diff --git a/db/migrate/20111019212429_add_social_to_user.rb b/db/migrate/20111019212429_add_social_to_user.rb new file mode 100644 index 00000000..b0ffe536 --- /dev/null +++ b/db/migrate/20111019212429_add_social_to_user.rb @@ -0,0 +1,7 @@ +class AddSocialToUser < ActiveRecord::Migration + def change + add_column :users, :skype, :string + add_column :users, :linkedin, :string + add_column :users, :twitter, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index a8196976..6408792f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111016195506) do +ActiveRecord::Schema.define(:version => 20111019212429) do create_table "issues", :force => true do |t| t.string "title" @@ -82,6 +82,9 @@ ActiveRecord::Schema.define(:version => 20111016195506) do t.string "name" t.boolean "admin", :default => false, :null => false t.integer "projects_limit", :default => 10 + t.string "skype" + t.string "linkedin" + t.string "twitter" end add_index "users", ["email"], :name => "index_users_on_email", :unique => true diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 77abe2ca..32fb90a3 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -39,5 +39,8 @@ end # name :string(255) # admin :boolean default(FALSE), not null # projects_limit :integer +# skype :string +# linkedin :string +# twitter :string # diff --git a/spec/requests/profile_spec.rb b/spec/requests/profile_spec.rb index 07fdc4ab..5838f63b 100644 --- a/spec/requests/profile_spec.rb +++ b/spec/requests/profile_spec.rb @@ -14,6 +14,22 @@ describe "Profile" do it { page.should have_content(@user.email) } end + describe "Profile update" do + before do + visit profile_path + fill_in "user_skype", :with => "testskype" + fill_in "user_linkedin", :with => "testlinkedin" + fill_in "user_twitter", :with => "testtwitter" + click_button "Save" + @user.reload + end + + it { @user.skype.should == 'testskype' } + it { @user.linkedin.should == 'testlinkedin' } + it { @user.twitter.should == 'testtwitter' } + end + + describe "Password update" do before do visit profile_password_path From 0f0c562de09e325c5689b3db8e646b68322f5515 Mon Sep 17 00:00:00 2001 From: Adam Leonard Date: Thu, 20 Oct 2011 09:48:09 -0400 Subject: [PATCH 066/176] Add check to ensure that a team member has atleast one Access Role selected --- app/models/users_project.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/models/users_project.rb b/app/models/users_project.rb index bdc10633..96e2d16a 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -9,7 +9,8 @@ class UsersProject < ActiveRecord::Base validates_uniqueness_of :user_id, :scope => [:project_id] validates_presence_of :user_id validates_presence_of :project_id - + validate :user_has_a_role_selected + delegate :name, :email, :to => :user, :prefix => true def update_gitosis_project @@ -18,6 +19,10 @@ class UsersProject < ActiveRecord::Base end end + def user_has_a_role_selected + errors.add(:base, "Please choose at least one Role in the Access list") unless read || write || admin + end + end # == Schema Information # From 48924dfeeafbe965ec06797b10010ebd8a5dcfcd Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 20 Oct 2011 19:21:58 +0300 Subject: [PATCH 067/176] Wall redesign --- app/assets/javascripts/application.js | 4 +++ app/assets/stylesheets/projects.css.scss | 32 ++++++++++++++++--- app/controllers/projects_controller.rb | 11 +++++-- app/views/commits/_commits.html.haml | 4 +-- app/views/commits/show.js.haml | 4 ++- app/views/notes/_form.html.haml | 4 +-- app/views/notes/_notes.html.haml | 17 +++++----- app/views/notes/_show.html.haml | 12 +++---- app/views/notes/create.js.haml | 2 +- app/views/projects/_recent_commits.html.haml | 4 +-- app/views/projects/_recent_messages.html.haml | 6 ---- app/views/projects/wall.html.haml | 25 +++++++++++++++ 12 files changed, 89 insertions(+), 36 deletions(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 01e3b416..024dfe11 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -16,3 +16,7 @@ $(function(){ $('select#branch').selectmenu({style:'popup', width:200}); $('select#tag').selectmenu({style:'popup', width:200}); }); + +function updatePage(){ + $.ajax({type: "GET", url: location.href, dataType: "script"}); +} diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 860523b0..51788672 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -491,8 +491,14 @@ tbody tr:nth-child(2n) td, tbody tr.even td { background: white; } p { - margin-bottom: 3px; - font-size: 12px; + margin-bottom: 4px; + font-size: 13px; + color:#111; + } + } + cite { + &.ago { + color:#666; } } } @@ -515,7 +521,7 @@ tbody tr:nth-child(2n) td, tbody tr.even td { } .note_content { float:left; - width:750px; + width:650px; } .issue_notes { @@ -605,7 +611,9 @@ tbody tr:nth-child(2n) td, tbody tr.even td { } } -.message{ +.commit, +.message, +#notes-list{ .author { background: #eaeaea; color: #333; @@ -614,3 +622,19 @@ tbody tr:nth-child(2n) td, tbody tr.even td { margin-right:5px; } } + +/* Note textare */ +#note_note { + height:100px; + width:97%; + font-size:14px; +} + +.wall_page { + #note_note { + height:25px; + } + .attach_holder { + display:none; + } +} diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 8ce3ca97..dc94bae2 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -75,7 +75,7 @@ class ProjectsController < ApplicationController y.committed_date <=> x.committed_date end - @messages = project.notes.since(@date).limit(40).order("created_at DESC") + @messages = project.notes.since(@date).order("created_at DESC") else return render "projects/empty" end @@ -86,7 +86,14 @@ class ProjectsController < ApplicationController # def wall - @notes = @project.common_notes + @date = case params[:view] + when "week" then Date.today - 7.days + when "all" then nil + else Date.today + end + + @notes = @project.common_notes.order("created_at DESC") + @notes = @notes.since(@date.at_beginning_of_day) if @date @note = Note.new end diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index 5a3ba3a7..94a1bd1b 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -15,8 +15,8 @@ = link_to "Browse Code", tree_project_path(@project, :commit_id => commit.id), :class => "lite_button", :style => "float:right" = link_to truncate(commit.id.to_s, :length => 16), project_commit_path(@project, :id => commit.id), :class => "lite_button", :style => "width:120px;float:right" %span - %span - [ #{commit.author} ] + %span.author + = commit.author = time_ago_in_words(commit.committed_date) ago = more_commits_link if @commits.size > 99 diff --git a/app/views/commits/show.js.haml b/app/views/commits/show.js.haml index 2c46689b..cec1fe28 100644 --- a/app/views/commits/show.js.haml +++ b/app/views/commits/show.js.haml @@ -1,6 +1,8 @@ -:plain +-#:plain $("#side-commit-preview").remove(); var side = $("
      "); side.html("#{escape_javascript(render "commits/show")}"); $("##{dom_id(@project)}").parent().append(side); $("##{dom_id(@project)}").addClass("span-14"); +:plain + $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index 8eaf968c..ca56a245 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -12,9 +12,9 @@ = f.label :note %cite (255 symbols only) %br - = f.text_area :note, :style => "width:97%;height:100px", :size => 255 + = f.text_area :note, :size => 255 - %div + %div.attach_holder = f.label :attachment %cite (less than 10 MB) %br diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml index c93a4723..2d110162 100644 --- a/app/views/notes/_notes.html.haml +++ b/app/views/notes/_notes.html.haml @@ -1,9 +1,12 @@ -%ul#notes-list= render "notes/notes_list" +- if controller.action_name == "wall" + %ul#notes-list= render "notes/notes_list" -%br -%br -- if can? current_user, :write_note, @project - = render "notes/form" +- else + %ul#notes-list= render "notes/notes_list" + %br + %br + - if can? current_user, :write_note, @project + = render "notes/form" :javascript $('.delete-note').live('ajax:success', function() { @@ -23,7 +26,3 @@ $(function(){ var int =self.setInterval("updatePage()", 20000); }); - - function updatePage(){ - $.ajax({type: "GET", url: location.href, dataType: "script"}); - } diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_show.html.haml index 2b0a6d2e..ee9f9ffa 100644 --- a/app/views/notes/_show.html.haml +++ b/app/views/notes/_show.html.haml @@ -1,19 +1,17 @@ %li{:id => dom_id(note)} %div.note_author = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" - %div.note_content + %div.note_content.left = simple_format(html_escape(note.note)) - if note.attachment.url Attachment: - = link_to note.attachment_identifier, note.attachment.url + = link_to note.attachment_identifier, note.attachment.url, :target => "_blank" %br - %span - %span - [ #{note.author.name} ] -   + %span.author= note.author.name + %cite.ago = time_ago_in_words(note.updated_at) ago - %br + %br - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) = link_to 'Remove', [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-note right negative" .clear diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index 0af548ff..15371dbc 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -1,7 +1,7 @@ - if @note.valid? :plain $("#new_note .errors").remove(); - $("#notes-list").append("#{escape_javascript(render(:partial => 'show', :locals => {:note => @note} ))}"); + updatePage(); $('#note_note').val(""); - else :plain diff --git a/app/views/projects/_recent_commits.html.haml b/app/views/projects/_recent_commits.html.haml index 812be93c..e435ea30 100644 --- a/app/views/projects/_recent_commits.html.haml +++ b/app/views/projects/_recent_commits.html.haml @@ -9,8 +9,8 @@ = link_to truncate_commit_message(commit, 60), project_commit_path(@project, :id => commit.id) %span - %span - [ #{commit.author} ] + %span.author + = commit.author.name.force_encoding("UTF-8") %cite = time_ago_in_words(commit.committed_date) ago diff --git a/app/views/projects/_recent_messages.html.haml b/app/views/projects/_recent_messages.html.haml index 03f723da..1af7fe3b 100644 --- a/app/views/projects/_recent_messages.html.haml +++ b/app/views/projects/_recent_messages.html.haml @@ -46,12 +46,6 @@ Attachment: = link_to note.attachment_identifier, note.attachment.url %br - -#%span - %span - [ #{note.author.name} ] - %cite - = time_ago_in_words(note.created_at) - ago %br .append-bottom   diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml index 479bb3cf..d3dcb353 100644 --- a/app/views/projects/wall.html.haml +++ b/app/views/projects/wall.html.haml @@ -1 +1,26 @@ +%div.wall_page + - if can? current_user, :write_note, @project + = render "notes/form" + .right + = form_tag wall_project_path(@project), :method => :get do + .span-2 + = radio_button_tag :view, "day", (params[:view] || "day") == "day", :onclick => "this.form.submit()", :id => "day_view" + = label_tag "day_view","Today" + .span-2 + = radio_button_tag :view, "week", params[:view] == "week", :onclick => "this.form.submit()", :id => "week_view" + = label_tag "week_view","Week" + .span-2 + = radio_button_tag :view, "all", params[:view] == "all", :onclick => "this.form.submit()", :id => "all_view" + = label_tag "all_view","All" + .clear + %br + %hr = render "notes/notes" + +:javascript + $(function(){ + $("#note_note").live("click", function(){ + $(this).css("height", "100px"); + $('.attach_holder').show(); + }); + }); From c463eeb0908e5c00008073c07e71e06434393342 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 20 Oct 2011 22:00:00 +0300 Subject: [PATCH 068/176] refactoring --- app/helpers/application_helper.rb | 21 ----------- app/models/snippet.rb | 7 ++++ app/views/commits/_diff.html.haml | 7 ++-- app/views/projects/_tree_file.html.haml | 10 +++--- app/views/snippets/show.html.haml | 3 +- config/initializers/grit_ext.rb | 8 +++++ lib/utils.rb | 47 ++++++++++++++++++++++--- 7 files changed, 66 insertions(+), 37 deletions(-) create mode 100644 config/initializers/grit_ext.rb diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c389fd4a..0895eb0d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -53,25 +53,4 @@ module ApplicationHelper [projects, default_nav, project_nav].flatten.to_json end - def handle_file_type(file_name, mime_type = nil) - if file_name =~ /(\.rb|\.ru|\.rake|Rakefile|\.gemspec|\.rbx|Gemfile)$/ - :ruby - elsif file_name =~ /\.py$/ - :python - elsif file_name =~ /(\.pl|\.scala|\.c|\.cpp|\.java|\.haml|\.html|\.sass|\.scss|\.xml|\.php|\.erb)$/ - $1[1..-1].to_sym - elsif file_name =~ /\.js$/ - :javascript - elsif file_name =~ /\.sh$/ - :bash - elsif file_name =~ /\.coffee$/ - :coffeescript - elsif file_name =~ /\.yml$/ - :yaml - elsif file_name =~ /\.md$/ - :minid - else - :text - end - end end diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 0a54fee7..119b69a4 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -1,4 +1,6 @@ class Snippet < ActiveRecord::Base + include Utils::Colorize + belongs_to :project belongs_to :author, :class_name => "User" has_many :notes, :as => :noteable @@ -28,6 +30,11 @@ class Snippet < ActiveRecord::Base ".js", ".sh", ".coffee", ".yml", ".md" ] end + + def colorize + ft = handle_file_type(file_name) + Albino.colorize(content, ft, :html, 'utf-8', "linenos=True") + end end # == Schema Information # diff --git a/app/views/commits/_diff.html.haml b/app/views/commits/_diff.html.haml index dff99bf1..73652aaf 100644 --- a/app/views/commits/_diff.html.haml +++ b/app/views/commits/_diff.html.haml @@ -1,4 +1,3 @@ -- require "utils" .file_stats - @commit.diffs.each do |diff| - if diff.deleted_file @@ -35,7 +34,7 @@ %strong{:id => "#{diff.b_path}"}= diff.b_path %br/ .diff_file_content - - if file.mime_type =~ /application|text/ && !Utils.binary?(file.data) + - if file.text? - lines_arr = diff.diff.lines.to_a - line_old = lines_arr[2].match(/-(\d)/)[0].to_i.abs rescue 0 - line_new = lines_arr[2].match(/\+(\d)/)[0].to_i.abs rescue 0 @@ -50,9 +49,9 @@ - else - line_new += 1 - line_old += 1 - - elsif file.mime_type =~ /image/ + - elsif file.image? .diff_file_content_image - %img{:src => "data:image/jpeg;base64,#{Base64.encode64(file.data)}"} + %img{:src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} - else %p %center No preview for this file type diff --git a/app/views/projects/_tree_file.html.haml b/app/views/projects/_tree_file.html.haml index 3463bfc5..ae95d483 100644 --- a/app/views/projects/_tree_file.html.haml +++ b/app/views/projects/_tree_file.html.haml @@ -1,4 +1,3 @@ -- require "utils" .view_file .view_file_header %strong @@ -6,14 +5,13 @@ = link_to "raw", blob_project_path(@project, :commit_id => @commit.id, :path => params[:path] ), :class => "right", :target => "_blank" = link_to "history", project_commits_path(@project, :path => params[:path]), :class => "right", :style => "margin-right:10px;" %br/ - - if file.mime_type =~ /application|text/ && !Utils.binary?(file.data) + - if file.text? .view_file_content - - ft = handle_file_type(file.name, file.mime_type) :erb - <%= raw Albino.colorize(content, ft, :html, 'utf-8', "linenos=True") %> - - elsif file.mime_type =~ /image/ + <%= raw file.colorize %> + - elsif file.image? .view_file_content_image - %img{ :src => "data:image/jpeg;base64,#{Base64.encode64(file.data)}"} + %img{ :src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} - else %p %center No preview for this file type diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index bb444efe..899950b7 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -7,9 +7,8 @@ = @snippet.file_name %br/ .view_file_content - - ft = handle_file_type(@snippet.file_name) :erb - <%= raw Albino.colorize(@snippet.content, ft, :html, 'utf-8', "linenos=True") %> + <%= raw @snippet.colorize %> - if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user = link_to 'Edit', edit_project_snippet_path(@project, @snippet), :class => "lbutton positive" diff --git a/config/initializers/grit_ext.rb b/config/initializers/grit_ext.rb new file mode 100644 index 00000000..8f1329a6 --- /dev/null +++ b/config/initializers/grit_ext.rb @@ -0,0 +1,8 @@ +require 'grit' +require 'albino' +require "utils" + +Grit::Blob.class_eval do + include Utils::FileHelper + include Utils::Colorize +end diff --git a/lib/utils.rb b/lib/utils.rb index 6e7460ed..40bf2673 100644 --- a/lib/utils.rb +++ b/lib/utils.rb @@ -1,8 +1,47 @@ module Utils - def self.binary?(string) - string.each_byte do |x| - x.nonzero? or return true + module FileHelper + def binary?(string) + string.each_byte do |x| + x.nonzero? or return true + end + false + end + + def image? + mime_type =~ /image/ + end + + def text? + mime_type =~ /application|text/ && !binary?(data) + end + end + + module Colorize + def colorize + ft = handle_file_type(name, mime_type) + Albino.colorize(data, ft, :html, 'utf-8', "linenos=True") + end + + def handle_file_type(file_name, mime_type = nil) + if file_name =~ /(\.rb|\.ru|\.rake|Rakefile|\.gemspec|\.rbx|Gemfile)$/ + :ruby + elsif file_name =~ /\.py$/ + :python + elsif file_name =~ /(\.pl|\.scala|\.c|\.cpp|\.java|\.haml|\.html|\.sass|\.scss|\.xml|\.php|\.erb)$/ + $1[1..-1].to_sym + elsif file_name =~ /\.js$/ + :javascript + elsif file_name =~ /\.sh$/ + :bash + elsif file_name =~ /\.coffee$/ + :coffeescript + elsif file_name =~ /\.yml$/ + :yaml + elsif file_name =~ /\.md$/ + :minid + else + :text + end end - false end end From da48ca58914264cd58cf5e3863e9256d61b00d6a Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Fri, 21 Oct 2011 00:52:49 +0300 Subject: [PATCH 069/176] Issue #135 - Repository stay after project remove --- README.rdoc | 2 ++ lib/gitosis.rb | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.rdoc b/README.rdoc index 20097787..5e47b269 100644 --- a/README.rdoc +++ b/README.rdoc @@ -32,6 +32,8 @@ sqlite as default db # install this library first sudo easy_install pygments + + echo "gitlabhq ALL = (git) NOPASSWD: /bin/rm" | sudo tee -a /etc/sudoers sudo gem install bundler bundle diff --git a/lib/gitosis.rb b/lib/gitosis.rb index cab7da2d..59b3f2a2 100644 --- a/lib/gitosis.rb +++ b/lib/gitosis.rb @@ -42,7 +42,7 @@ class Gitosis end def destroy_project(project) - FileUtils.rm_rf(project.path_to_repo) + `rm -Rf #{project.path_to_repo}` conf = IniFile.new(File.join(@local_dir,'gitosis','gitosis.conf')) From b5a5e5a416a33147e99be2e8c07e2bcc7fb7ee6c Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 09:58:28 +0300 Subject: [PATCH 070/176] prepare for 1.1 --- CHANGELOG | 2 ++ VERSION | 2 +- update.rb | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index aa846166..96acfba1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,6 @@ v 1.1.0 + - project dashboard + - wall redesigned - feature: code snippets - fixed horizontal scroll on file preview - fixed app crash if commit message has invalid chars diff --git a/VERSION b/VERSION index 6d7de6e6..9084fa2f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.2 +1.1.0 diff --git a/update.rb b/update.rb index dccb7df3..b81a4088 100644 --- a/update.rb +++ b/update.rb @@ -19,8 +19,8 @@ env = if envs.include?(ARGV[0]) puts yellow "== RAILS ENV | #{env}" current_version = version puts yellow "Your version is #{current_version}" -puts yellow "Check for new version: $ git pull origin" -`git pull origin` # pull from origin +puts yellow "Check for new version: $ git pull origin 1x" +`git pull origin 1x` # pull from origin # latest version if version == current_version From a07923a549d53527442967aac9c4baf9596f3c1f Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 14:03:34 +0300 Subject: [PATCH 071/176] recent radio button --- app/controllers/projects_controller.rb | 32 ++++++++++++-------------- app/models/note.rb | 1 + app/models/project.rb | 28 ++++++++++++++++++++++ app/views/projects/show.html.haml | 7 ++++-- app/views/projects/wall.html.haml | 5 +++- spec/requests/projects_spec.rb | 2 +- 6 files changed, 54 insertions(+), 21 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index dc94bae2..5ccfe4bb 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -60,24 +60,21 @@ class ProjectsController < ApplicationController end def show - if @project.repo_exists? - @date = case params[:view] - when "week" then Date.today - 7.days - else Date.today - end.at_beginning_of_day + return render "projects/empty" unless @project.repo_exists? + @date = case params[:view] + when "week" then Date.today - 7.days + when "day" then Date.today + else nil + end - @heads = @project.repo.heads - @commits = @heads.map do |h| - @project.repo.log(h.name, nil, :since => @date) - end.flatten.uniq { |c| c.id } - - @commits.sort! do |x, y| - y.committed_date <=> x.committed_date - end + if @date + @date = @date.at_beginning_of_day + @commits = @project.commits_since(@date) @messages = project.notes.since(@date).order("created_at DESC") - else - return render "projects/empty" + else + @commits = @project.fresh_commits + @messages = project.notes.fresh.limit(10) end end @@ -89,11 +86,12 @@ class ProjectsController < ApplicationController @date = case params[:view] when "week" then Date.today - 7.days when "all" then nil - else Date.today + when "day" then Date.today + else nil end @notes = @project.common_notes.order("created_at DESC") - @notes = @notes.since(@date.at_beginning_of_day) if @date + @notes = @date ? @notes.since(@date.at_beginning_of_day) : @notes.fresh.limit(10) @note = Note.new end diff --git a/app/models/note.rb b/app/models/note.rb index 71fd9dcd..e3dabce4 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -24,6 +24,7 @@ class Note < ActiveRecord::Base scope :last_week, where("created_at >= :date", :date => (Date.today - 7.days)) scope :since, lambda { |day| where("created_at >= :date", :date => (day)) } + scope :fresh, order("created_at DESC") mount_uploader :attachment, AttachmentUploader end diff --git a/app/models/project.rb b/app/models/project.rb index f51bd9b3..d70b18e7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -126,6 +126,34 @@ class Project < ActiveRecord::Base end end + def heads + @heads ||= repo.heads + end + + def fresh_commits + commits = heads.map do |h| + repo.commits(h.name, 10) + end.flatten.uniq { |c| c.id } + + commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end + + commits[0..10] + end + + def commits_since(date) + commits = heads.map do |h| + repo.log(h.name, nil, :since => date) + end.flatten.uniq { |c| c.id } + + commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end + + commits + end + def tree(fcommit, path = nil) fcommit = commit if fcommit == :head tree = fcommit.tree diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index ff6078c1..85019ecb 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -1,9 +1,12 @@ %div - %h2.left Recent history + %h2.left History .right = form_tag project_path(@project), :method => :get do .span-2 - = radio_button_tag :view, "day", (params[:view] || "day") == "day", :onclick => "this.form.submit()", :id => "day_view" + = radio_button_tag :view, "recent", (params[:view] || "recent") == "recent", :onclick => "this.form.submit()", :id => "recent_view" + = label_tag "recent_view","Recent" + .span-2 + = radio_button_tag :view, "day", params[:view] == "day", :onclick => "this.form.submit()", :id => "day_view" = label_tag "day_view","Today" .span-2 = radio_button_tag :view, "week", params[:view] == "week", :onclick => "this.form.submit()", :id => "week_view" diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml index d3dcb353..ed22478c 100644 --- a/app/views/projects/wall.html.haml +++ b/app/views/projects/wall.html.haml @@ -4,7 +4,10 @@ .right = form_tag wall_project_path(@project), :method => :get do .span-2 - = radio_button_tag :view, "day", (params[:view] || "day") == "day", :onclick => "this.form.submit()", :id => "day_view" + = radio_button_tag :view, "recent", (params[:view] || "recent") == "recent", :onclick => "this.form.submit()", :id => "recent_view" + = label_tag "recent_view","Recent" + .span-2 + = radio_button_tag :view, "day", params[:view] == "day", :onclick => "this.form.submit()", :id => "day_view" = label_tag "day_view","Today" .span-2 = radio_button_tag :view, "week", params[:view] == "week", :onclick => "this.form.submit()", :id => "week_view" diff --git a/spec/requests/projects_spec.rb b/spec/requests/projects_spec.rb index a1bac062..945c1ea2 100644 --- a/spec/requests/projects_spec.rb +++ b/spec/requests/projects_spec.rb @@ -73,7 +73,7 @@ describe "Projects" do end it "should beahave like dashboard" do - page.should have_content("Recent history") + page.should have_content("History") end end From f2808191893d2d3f158f569627ac6005509ea05b Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 14:25:42 +0300 Subject: [PATCH 072/176] fixed wall --all option --- app/controllers/projects_controller.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 5ccfe4bb..54d19af7 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -83,16 +83,15 @@ class ProjectsController < ApplicationController # def wall - @date = case params[:view] - when "week" then Date.today - 7.days - when "all" then nil - when "day" then Date.today - else nil - end - - @notes = @project.common_notes.order("created_at DESC") - @notes = @date ? @notes.since(@date.at_beginning_of_day) : @notes.fresh.limit(10) @note = Note.new + @notes = @project.common_notes.order("created_at DESC") + + @notes = case params[:view] + when "week" then @notes.since((Date.today - 7.days).at_beginning_of_day) + when "all" then @notes.all + when "day" then @notes.since(Date.today.at_beginning_of_day) + else @notes.fresh.limit(10) + end end # From 1477a6c8aaecbde1f2b5903cccb267d632212ee4 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 15:35:42 +0300 Subject: [PATCH 073/176] moved from albino -> pygments.rb --- Gemfile | 2 +- Gemfile.lock | 15 +++++++-------- app/models/snippet.rb | 3 +-- app/views/projects/_tree_file.html.haml | 1 + app/views/projects/empty.html.erb | 7 ++++--- config/initializers/grit_ext.rb | 2 +- lib/utils.rb | 8 ++++++-- 7 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Gemfile b/Gemfile index 523793e7..77a00659 100644 --- a/Gemfile +++ b/Gemfile @@ -15,7 +15,7 @@ gem 'therubyracer' gem 'faker' gem 'seed-fu', :git => 'git://github.com/mbleigh/seed-fu.git' gem "inifile" -gem "albino", :git => "git://github.com/gitlabhq/albino.git" +gem "pygments.rb", "0.2.3" gem "kaminari" gem "thin" gem "git" diff --git a/Gemfile.lock b/Gemfile.lock index 2aa894aa..5ba34459 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -4,13 +4,6 @@ GIT specs: annotate (2.4.1.beta1) -GIT - remote: git://github.com/gitlabhq/albino.git - revision: 118380924969f3a856659f86ea1f40c1ba7bfcb1 - specs: - albino (1.3.3) - posix-spawn (>= 0.3.6) - GIT remote: git://github.com/gitlabhq/grit.git revision: ff015074ef35bd94cba943f9c0f98e161ab5851c @@ -72,6 +65,7 @@ GEM ZenTest (= 4.5) awesome_print (0.4.0) bcrypt-ruby (3.0.1) + blankslate (2.1.2.4) builder (3.0.0) capybara (1.0.1) mime-types (>= 1.16) @@ -138,6 +132,8 @@ GEM orm_adapter (0.0.5) polyglot (0.3.2) posix-spawn (0.3.6) + pygments.rb (0.2.3) + rubypython (>= 0.5.1) rack (1.3.2) rack-cache (1.0.3) rack (>= 0.4) @@ -189,6 +185,9 @@ GEM ruby-debug-base19 (>= 0.11.19) ruby_core_source (0.1.5) archive-tar-minitar (>= 0.5.2) + rubypython (0.5.1) + blankslate (>= 2.1.2.3) + ffi (~> 1.0.7) rubyzip (0.9.4) sass (3.1.7) sass-rails (3.1.1) @@ -242,7 +241,6 @@ PLATFORMS DEPENDENCIES acts_as_list - albino! annotate! autotest autotest-rails @@ -260,6 +258,7 @@ DEPENDENCIES jquery-rails kaminari launchy + pygments.rb (= 0.2.3) rails (= 3.1.0) rails-footnotes (>= 3.7.5.rc4) rspec-rails diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 119b69a4..95d6a07d 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -32,8 +32,7 @@ class Snippet < ActiveRecord::Base end def colorize - ft = handle_file_type(file_name) - Albino.colorize(content, ft, :html, 'utf-8', "linenos=True") + system_colorize(content, file_name) end end # == Schema Information diff --git a/app/views/projects/_tree_file.html.haml b/app/views/projects/_tree_file.html.haml index ae95d483..41a2287a 100644 --- a/app/views/projects/_tree_file.html.haml +++ b/app/views/projects/_tree_file.html.haml @@ -1,3 +1,4 @@ +:css .view_file .view_file_header %strong diff --git a/app/views/projects/empty.html.erb b/app/views/projects/empty.html.erb index a8917471..4c60facd 100644 --- a/app/views/projects/empty.html.erb +++ b/app/views/projects/empty.html.erb @@ -1,3 +1,4 @@ +<% bash_lexer = Pygments::Lexer[:bash] %>

      Git global setup:

      @@ -6,7 +7,7 @@ git config --global user.name "#{current_user.name}" git config --global user.email "#{current_user.email}" eos %> - <%= raw Albino.colorize(setup_str, :bash) %> + <%= raw bash_lexer.highlight(setup_str) %>

      Next steps:

      @@ -21,7 +22,7 @@ git remote add origin #{@project.url_to_repo} git push -u origin master eos %> - <%= raw Albino.colorize(repo_setup_str, :bash) %> + <%= raw bash_lexer.highlight(repo_setup_str) %>

      Existing Git Repo?

      @@ -31,7 +32,7 @@ git remote add origin #{@project.url_to_repo} git push -u origin master eos %> - <%= raw Albino.colorize(exist_repo_setup_str, :bash) %> + <%= raw bash_lexer.highlight(exist_repo_setup_str) %>

      Remove this project?

      diff --git a/config/initializers/grit_ext.rb b/config/initializers/grit_ext.rb index 8f1329a6..4bd71003 100644 --- a/config/initializers/grit_ext.rb +++ b/config/initializers/grit_ext.rb @@ -1,5 +1,5 @@ require 'grit' -require 'albino' +require 'pygments' require "utils" Grit::Blob.class_eval do diff --git a/lib/utils.rb b/lib/utils.rb index 40bf2673..e57121a3 100644 --- a/lib/utils.rb +++ b/lib/utils.rb @@ -18,8 +18,12 @@ module Utils module Colorize def colorize - ft = handle_file_type(name, mime_type) - Albino.colorize(data, ft, :html, 'utf-8', "linenos=True") + system_colorize(data, name) + end + + def system_colorize(data, file_name) + ft = handle_file_type(file_name) + Pygments.highlight(data, :lexer => ft, :options => { :encoding => 'utf-8', :linenos => 'True' }) end def handle_file_type(file_name, mime_type = nil) From cee932500caf2d903e08f063772c570db4158925 Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Fri, 21 Oct 2011 15:56:37 +0300 Subject: [PATCH 074/176] now you can view comrade profile info #134 --- app/views/projects/_top_menu.html.haml | 2 +- app/views/team_members/_show.html.haml | 6 ++-- app/views/team_members/show.html.haml | 28 +++++++++++++++++++ ...021101550_change_social_fields_in_users.rb | 10 +++++++ db/schema.rb | 8 +++--- spec/requests/team_members_spec.rb | 9 ++++++ spec/support/login.rb | 3 +- 7 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 app/views/team_members/show.html.haml create mode 100644 db/migrate/20111021101550_change_social_fields_in_users.rb diff --git a/app/views/projects/_top_menu.html.haml b/app/views/projects/_top_menu.html.haml index e281b93b..59f2533e 100644 --- a/app/views/projects/_top_menu.html.haml +++ b/app/views/projects/_top_menu.html.haml @@ -5,7 +5,7 @@ %span= link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil %span= link_to "Commits", project_commits_path(@project), :class => current_page?(:controller => "commits", :action => "index", :project_id => @project) ? "current" : nil %span - = link_to team_project_path(@project), :class => current_page?(:controller => "projects", :action => "team", :id => @project) ? "current" : nil do + = link_to team_project_path(@project), :class => (current_page?(:controller => "projects", :action => "team", :id => @project) || controller.controller_name == "team_members") ? "current" : nil do Team - if @project.users_projects.count > 0 %span{ :class => "top_menu_count" }= @project.users_projects.count diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml index 6d310768..b9a68e6c 100644 --- a/app/views/team_members/_show.html.haml +++ b/app/views/team_members/_show.html.haml @@ -1,8 +1,10 @@ - user = member.user %tr{:id => dom_id(member)} %td - = image_tag gravatar_icon(user.email), :class => "left", :width => 40, :style => "padding:0 5px;" - = truncate user.name, :lenght => 16 + = link_to image_tag(gravatar_icon(user.email), :class => "left", :width => 40, :style => "padding:0 5px;"), project_team_member_path(@project, member) + + = link_to truncate(user.name, :lenght => 16), project_team_member_path(@project, member) + %td= truncate user.email, :lenght => 16 - if can? current_user, :admin_project, @project = form_for(member, :as => :team_member, :url => project_team_member_path(@project, member)) do |f| diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml new file mode 100644 index 00000000..d07c54f8 --- /dev/null +++ b/app/views/team_members/show.html.haml @@ -0,0 +1,28 @@ +- user = @team_member.user +.span-2 + = image_tag gravatar_icon(user.email), :class => "left", :width => 60, :style => "padding-right:5px;" +%p + %b Name: + = user.name +%p + %b Email: + = user.email + +%br + +- unless user.skype.empty? + .div + %b Skype: + = user.skype + +- unless user.linkedin.empty? + .div + %b LinkedIn: + = user.linkedin + +- unless user.twitter.empty? + .div + %b Twitter: + = user.twitter + + diff --git a/db/migrate/20111021101550_change_social_fields_in_users.rb b/db/migrate/20111021101550_change_social_fields_in_users.rb new file mode 100644 index 00000000..6f05c05d --- /dev/null +++ b/db/migrate/20111021101550_change_social_fields_in_users.rb @@ -0,0 +1,10 @@ +class ChangeSocialFieldsInUsers < ActiveRecord::Migration + def up + change_column(:users, :skype, :string, {:null => false, :default => ''}) + change_column(:users, :linkedin, :string, {:null => false, :default => ''}) + change_column(:users, :twitter, :string, {:null => false, :default => ''}) + end + + def down + end +end diff --git a/db/schema.rb b/db/schema.rb index 6408792f..cc805990 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111019212429) do +ActiveRecord::Schema.define(:version => 20111021101550) do create_table "issues", :force => true do |t| t.string "title" @@ -82,9 +82,9 @@ ActiveRecord::Schema.define(:version => 20111019212429) do t.string "name" t.boolean "admin", :default => false, :null => false t.integer "projects_limit", :default => 10 - t.string "skype" - t.string "linkedin" - t.string "twitter" + t.string "skype", :default => "", :null => false + t.string "linkedin", :default => "", :null => false + t.string "twitter", :default => "", :null => false end add_index "users", ["email"], :name => "index_users_on_email", :unique => true diff --git a/spec/requests/team_members_spec.rb b/spec/requests/team_members_spec.rb index db7513ae..dd92febf 100644 --- a/spec/requests/team_members_spec.rb +++ b/spec/requests/team_members_spec.rb @@ -7,6 +7,15 @@ describe "TeamMembers" do @project.add_access(@user, :read, :admin) end + describe "View profile" do + it "should be available" do + visit(team_project_path(@project)) + find(:xpath, "//table[@id='team-table']//a[1]").click + page.should have_content @user.skype + page.should_not have_content 'Twitter' + end + end + describe "New Team member", :js => true do before do @user_1 = Factory :user diff --git a/spec/support/login.rb b/spec/support/login.rb index 09f64f9e..462647ab 100644 --- a/spec/support/login.rb +++ b/spec/support/login.rb @@ -3,7 +3,8 @@ module LoginMacros @user = User.create(:email => "user#{User.count}@mail.com", :name => "John Smith", :password => "123456", - :password_confirmation => "123456") + :password_confirmation => "123456", + :skype => 'user_skype') if role == :admin @user.admin = true From 86021a7dc397923afaf09d7602c34182f8064efe Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Fri, 21 Oct 2011 16:36:33 +0300 Subject: [PATCH 075/176] corrected last migration --- .../20111021101550_change_social_fields_in_users.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/db/migrate/20111021101550_change_social_fields_in_users.rb b/db/migrate/20111021101550_change_social_fields_in_users.rb index 6f05c05d..6e506c1c 100644 --- a/db/migrate/20111021101550_change_social_fields_in_users.rb +++ b/db/migrate/20111021101550_change_social_fields_in_users.rb @@ -1,8 +1,12 @@ class ChangeSocialFieldsInUsers < ActiveRecord::Migration def up - change_column(:users, :skype, :string, {:null => false, :default => ''}) - change_column(:users, :linkedin, :string, {:null => false, :default => ''}) - change_column(:users, :twitter, :string, {:null => false, :default => ''}) + remove_column :users, :skype + remove_column :users, :linkedin + remove_column :users, :twitter + + add_column :users, :skype, :string, {:null => false, :default => ''} + add_column :users, :linkedin, :string, {:null => false, :default => ''} + add_column :users, :twitter, :string, {:null => false, :default => ''} end def down From 6d0175e1f641415574a8fc48909af2cb3a357882 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 20:58:04 +0300 Subject: [PATCH 076/176] cleaning --- README.rdoc | 8 +++-- db/fixtures/development/001_admin.rb | 10 ++++++- db/fixtures/production/001_admin.rb | 9 ++++++ install.rb | 32 -------------------- update.rb | 44 ---------------------------- 5 files changed, 23 insertions(+), 80 deletions(-) delete mode 100644 install.rb delete mode 100644 update.rb diff --git a/README.rdoc b/README.rdoc index 20097787..74ffe15a 100644 --- a/README.rdoc +++ b/README.rdoc @@ -34,18 +34,19 @@ sqlite as default db sudo easy_install pygments sudo gem install bundler + bundle - RAILS_ENV=production rake db:setup + bundle exec rake db:setup RAILS_ENV=production # create admin user # login....admin@local.host # pass.....5iveL!fe - RAILS_ENV=production rake db:seed_fu + bundle exec rake db:seed_fu RAILS_ENV=production Install gitosis, edit conf/gitosis.yml & start server - rails s + rails s -e production == Install Gitosis sudo aptitude install gitosis @@ -63,6 +64,7 @@ Install gitosis, edit conf/gitosis.yml & start server ssh-keygen -t rsa sudo -H -u git gitosis-init < ~/.ssh/id_rsa.pub + sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update diff --git a/db/fixtures/development/001_admin.rb b/db/fixtures/development/001_admin.rb index 9c5a6da0..cfff6bf8 100644 --- a/db/fixtures/development/001_admin.rb +++ b/db/fixtures/development/001_admin.rb @@ -1,4 +1,3 @@ -# Admin account admin = User.create( :email => "admin@local.host", :name => "Administrator", @@ -9,3 +8,12 @@ admin = User.create( admin.projects_limit = 10000 admin.admin = true admin.save! + +if admin.valid? +puts %q[ +Administrator account created: + +login.........admin@local.host +password......5iveL!fe +] +end diff --git a/db/fixtures/production/001_admin.rb b/db/fixtures/production/001_admin.rb index 94d1abe8..cfff6bf8 100644 --- a/db/fixtures/production/001_admin.rb +++ b/db/fixtures/production/001_admin.rb @@ -8,3 +8,12 @@ admin = User.create( admin.projects_limit = 10000 admin.admin = true admin.save! + +if admin.valid? +puts %q[ +Administrator account created: + +login.........admin@local.host +password......5iveL!fe +] +end diff --git a/install.rb b/install.rb deleted file mode 100644 index a118cb5d..00000000 --- a/install.rb +++ /dev/null @@ -1,32 +0,0 @@ -root_path = File.expand_path(File.dirname(__FILE__)) -require File.join(root_path, "lib", "color") -include Color - -# -# ruby ./update.rb development # or test or production (default) -# -envs = ["production", "test", "development"] -env = if envs.include?(ARGV[0]) - ARGV[0] - else - "production" - end - -puts green " == Install for ENV=#{env} ..." - -# bundle install -`bundle install` - -# migrate db -`bundle exec rake db:create RAILS_ENV=#{env}` -`bundle exec rake db:schema:load RAILS_ENV=#{env}` -`bundle exec rake db:seed_fu RAILS_ENV=#{env}` - -puts green %q[ -Administrator account created: - -login.........admin@local.host -password......5iveL!fe -] - -puts green " == Done! Now you can start server" diff --git a/update.rb b/update.rb deleted file mode 100644 index b81a4088..00000000 --- a/update.rb +++ /dev/null @@ -1,44 +0,0 @@ -root_path = File.expand_path(File.dirname(__FILE__)) -require File.join(root_path, "lib", "color") -include Color - -def version - File.read("VERSION") -end - -# -# ruby ./update.rb development # or test or production (default) -# -envs = ["production", "test", "development"] -env = if envs.include?(ARGV[0]) - ARGV[0] - else - "production" - end - -puts yellow "== RAILS ENV | #{env}" -current_version = version -puts yellow "Your version is #{current_version}" -puts yellow "Check for new version: $ git pull origin 1x" -`git pull origin 1x` # pull from origin - -# latest version -if version == current_version - puts yellow "You have a latest version" -else - puts green "Update to #{version}" - -`bundle install` - - # migrate db -if env == "development" -`bundle exec rake db:migrate RAILS_ENV=development` -`bundle exec rake db:migrate RAILS_ENV=test` -else -`bundle exec rake db:migrate RAILS_ENV=#{env}` -end - - puts green "== Done! Now you can start/restart server" -end - - From 32f4dc7cf917d152d703e338219d1c718b97a003 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 21:14:55 +0300 Subject: [PATCH 077/176] link to file for commit diff --- app/views/commits/_diff.html.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/commits/_diff.html.haml b/app/views/commits/_diff.html.haml index 73652aaf..c88e5430 100644 --- a/app/views/commits/_diff.html.haml +++ b/app/views/commits/_diff.html.haml @@ -31,7 +31,8 @@ - if diff.deleted_file %strong{:id => "#{diff.b_path}"}= diff.a_path - else - %strong{:id => "#{diff.b_path}"}= diff.b_path + = link_to tree_file_project_path(@project, @commit.id, diff.b_path) do + %strong{:id => "#{diff.b_path}"}= diff.b_path %br/ .diff_file_content - if file.text? From e7570250afd88934d8435678b5c618d3ac202d17 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 21:40:36 +0300 Subject: [PATCH 078/176] fix #140, commit lil refactor --- app/models/project.rb | 8 +++++ app/views/commits/_diff.html.haml | 41 ++------------------------ app/views/commits/_diff_head.html.haml | 24 +++++++++++++++ app/views/commits/_text_file.html.haml | 15 ++++++++++ spec/models/project_spec.rb | 9 ++++++ 5 files changed, 59 insertions(+), 38 deletions(-) create mode 100644 app/views/commits/_diff_head.html.haml create mode 100644 app/views/commits/_text_file.html.haml diff --git a/app/models/project.rb b/app/models/project.rb index d70b18e7..1dd04e1f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -36,6 +36,8 @@ class Project < ActiveRecord::Base validate :check_limit + validate :repo_name + after_destroy :destroy_gitosis_project after_save :update_gitosis_project @@ -168,6 +170,12 @@ class Project < ActiveRecord::Base errors[:base] << ("Cant check your ability to create project") end + def repo_name + if path == "gitosis-admin" + errors.add(:path, "Project path like 'gitosis-admin' is not allowed") + end + end + def valid_repo? repo rescue diff --git a/app/views/commits/_diff.html.haml b/app/views/commits/_diff.html.haml index c88e5430..2807e090 100644 --- a/app/views/commits/_diff.html.haml +++ b/app/views/commits/_diff.html.haml @@ -1,27 +1,5 @@ -.file_stats - - @commit.diffs.each do |diff| - - if diff.deleted_file - %span.removed_file - %a{:href => "##{diff.a_path}"} - = diff.a_path - = image_tag "blueprint_delete.png" - - elsif diff.renamed_file - %span.moved_file - %a{:href => "##{diff.b_path}"} - = diff.a_path - = "->" - = diff.b_path - = image_tag "blueprint_notice.png" - - elsif diff.new_file - %span.new_file - %a{:href => "##{diff.b_path}"} - = diff.b_path - = image_tag "blueprint_add.png" - - else - %span.edit_file - %a{:href => "##{diff.b_path}"} - = diff.b_path - = image_tag "blueprint_info.png" +.file_stats= render "commits/diff_head" + - @commit.diffs.each do |diff| - next if diff.diff.empty? - file = (@commit.tree / diff.b_path) @@ -36,20 +14,7 @@ %br/ .diff_file_content - if file.text? - - lines_arr = diff.diff.lines.to_a - - line_old = lines_arr[2].match(/-(\d)/)[0].to_i.abs rescue 0 - - line_new = lines_arr[2].match(/\+(\d)/)[0].to_i.abs rescue 0 - - lines = lines_arr[3..-1].join - - lines.each_line do |line| - = diff_line(line, line_new, line_old) - - if line[0] == "+" - - line_new += 1 - - elsif - - line[0] == "-" - - line_old += 1 - - else - - line_new += 1 - - line_old += 1 + = render :partial => "commits/text_file", :locals => { :diff => diff } - elsif file.image? .diff_file_content_image %img{:src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} diff --git a/app/views/commits/_diff_head.html.haml b/app/views/commits/_diff_head.html.haml new file mode 100644 index 00000000..922c3599 --- /dev/null +++ b/app/views/commits/_diff_head.html.haml @@ -0,0 +1,24 @@ +- @commit.diffs.each do |diff| + - if diff.deleted_file + %span.removed_file + %a{:href => "##{diff.a_path}"} + = diff.a_path + = image_tag "blueprint_delete.png" + - elsif diff.renamed_file + %span.moved_file + %a{:href => "##{diff.b_path}"} + = diff.a_path + = "->" + = diff.b_path + = image_tag "blueprint_notice.png" + - elsif diff.new_file + %span.new_file + %a{:href => "##{diff.b_path}"} + = diff.b_path + = image_tag "blueprint_add.png" + - else + %span.edit_file + %a{:href => "##{diff.b_path}"} + = diff.b_path + = image_tag "blueprint_info.png" + diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml new file mode 100644 index 00000000..b20aa8af --- /dev/null +++ b/app/views/commits/_text_file.html.haml @@ -0,0 +1,15 @@ +- lines_arr = diff.diff.lines.to_a +- line_old = lines_arr[2].match(/-(\d)/)[0].to_i.abs rescue 0 +- line_new = lines_arr[2].match(/\+(\d)/)[0].to_i.abs rescue 0 +- lines = lines_arr[3..-1].join +- lines.each_line do |line| + = diff_line(line, line_new, line_old) + - if line[0] == "+" + - line_new += 1 + - elsif + - line[0] == "-" + - line_old += 1 + - else + - line_new += 1 + - line_old += 1 + diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 6ed8653d..0c62743d 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -4,11 +4,15 @@ describe Project do describe "Associations" do it { should have_many(:users) } it { should have_many(:users_projects) } + it { should have_many(:issues) } + it { should have_many(:notes) } + it { should have_many(:snippets) } end describe "Validation" do it { should validate_presence_of(:name) } it { should validate_presence_of(:path) } + it { should validate_presence_of(:code) } end describe "Respond to" do @@ -31,6 +35,11 @@ describe Project do it { should respond_to(:commit) } end + it "should not allow 'gitosis-admin' as repo name" do + should allow_value("blah").for(:path) + should_not allow_value("gitosis-admin").for(:path) + end + it "should return valid url to repo" do project = Project.new(:path => "somewhere") project.url_to_repo.should == "git@localhost:somewhere.git" From 421b11158d8420b3fe337b63d5686c24b5644c94 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 21:51:55 +0300 Subject: [PATCH 079/176] error fields highlight --- app/assets/stylesheets/projects.css.scss | 9 +++++++++ app/models/project.rb | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 51788672..8caa2810 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -638,3 +638,12 @@ tbody tr:nth-child(2n) td, tbody tr.even td { display:none; } } + +.field_with_errors { + input[type="text"], + input[type="password"], + textarea + { + background: none repeat scroll 0 0 #FFBBBB + } +} diff --git a/app/models/project.rb b/app/models/project.rb index 1dd04e1f..5262e552 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -35,7 +35,6 @@ class Project < ActiveRecord::Base :presence => true validate :check_limit - validate :repo_name after_destroy :destroy_gitosis_project @@ -172,7 +171,7 @@ class Project < ActiveRecord::Base def repo_name if path == "gitosis-admin" - errors.add(:path, "Project path like 'gitosis-admin' is not allowed") + errors.add(:path, " like 'gitosis-admin' is not allowed") end end From ecd462a606b1f9fc36a46daea95d09eddddd9e89 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 22:44:08 +0300 Subject: [PATCH 080/176] test cov --- app/controllers/team_members_controller.rb | 28 ++++++---------------- spec/requests/team_members_spec.rb | 26 ++++++++++++++++---- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb index 5fb2710d..84addf8d 100644 --- a/app/controllers/team_members_controller.rb +++ b/app/controllers/team_members_controller.rb @@ -8,35 +8,16 @@ class TeamMembersController < ApplicationController def show @team_member = project.users_projects.find(params[:id]) - - respond_to do |format| - format.html # show.html.erb - format.js - end end def new @team_member = project.users_projects.new - - respond_to do |format| - format.html # new.html.erb - format.js - end end def create @team_member = UsersProject.new(params[:team_member]) @team_member.project = project - - respond_to do |format| - if @team_member.save - format.html { redirect_to @team_member, notice: 'Team member was successfully created.' } - format.js - else - format.html { render action: "new" } - format.js - end - end + @team_member.save end def update @@ -45,7 +26,12 @@ class TeamMembersController < ApplicationController respond_to do |format| format.js - format.html { redirect_to team_project_path(@project)} + format.html do + unless @team_member.valid? + flash[:alert] = "User should have at least one role" + end + redirect_to team_project_path(@project) + end end end diff --git a/spec/requests/team_members_spec.rb b/spec/requests/team_members_spec.rb index dd92febf..ec0af321 100644 --- a/spec/requests/team_members_spec.rb +++ b/spec/requests/team_members_spec.rb @@ -29,19 +29,37 @@ describe "TeamMembers" do describe "fill in" do before do - check "team_member_read" click_link "Select user" click_link @user_1.name - #select @user_1.name, :from => "team_member_user_id" + + within "#team_member_new" do + check "team_member_read" + check "team_member_write" + end end - it { expect { click_button "Save" }.to change {UsersProject.count}.by(1) } + it { expect { click_button "Save";sleep(1) }.to change {UsersProject.count}.by(1) } it "should add new member to table" do click_button "Save" + @member = UsersProject.last - page.should_not have_content("Add new member") page.should have_content @user_1.name + + @member.read.should be_true + @member.write.should be_true + @member.admin.should be_false + end + + it "should not allow creation without access selected" do + within "#team_member_new" do + uncheck "team_member_read" + uncheck "team_member_write" + uncheck "team_member_admin" + end + + expect { click_button "Save" }.to_not change {UsersProject.count} + page.should have_content("Please choose at least one Role in the Access list") end end end From 5b284f6adf4cf17ffb66b32a5afdb2f754d5ad5f Mon Sep 17 00:00:00 2001 From: Adam Leonard Date: Sat, 22 Oct 2011 00:06:38 -0400 Subject: [PATCH 081/176] Add ability to Search issues --- Gemfile | 1 + Gemfile.lock | 2 ++ app/controllers/issues_controller.rb | 7 +++++++ app/views/issues/index.html.haml | 18 +++++++++++++++++- config/database.yml | 19 +++++++++---------- config/routes.rb | 3 +++ spec/requests/issues_spec.rb | 22 ++++++++++++++++++++++ 7 files changed, 61 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index 77a00659..ad15fc83 100644 --- a/Gemfile +++ b/Gemfile @@ -20,6 +20,7 @@ gem "kaminari" gem "thin" gem "git" gem "acts_as_list" +gem "mysql2" group :assets do gem 'sass-rails', " ~> 3.1.0" diff --git a/Gemfile.lock b/Gemfile.lock index 5ba34459..a881b05e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -128,6 +128,7 @@ GEM treetop (~> 1.4.8) mime-types (1.16) multi_json (1.0.3) + mysql2 (0.3.7) nokogiri (1.5.0) orm_adapter (0.0.5) polyglot (0.3.2) @@ -258,6 +259,7 @@ DEPENDENCIES jquery-rails kaminari launchy + mysql2 pygments.rb (= 0.2.3) rails (= 3.1.0) rails-footnotes (>= 3.7.5.rc4) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index cf8e1ebe..7b8c7cb5 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -78,6 +78,13 @@ class IssuesController < ApplicationController render :nothing => true end + def search + @project = Project.find(params['project']) + @issues = @project.issues.where("title LIKE ? OR content LIKE ?", "%#{params['terms']}%", "%#{params['terms']}%") + + render :partial => 'issues' + end + protected def issue diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml index 6f4548a8..53c4fe66 100644 --- a/app/views/issues/index.html.haml +++ b/app/views/issues/index.html.haml @@ -1,6 +1,10 @@ %div - if can? current_user, :write_issue, @project - .left= link_to 'New Issue', new_project_issue_path(@project), :remote => true, :class => "lbutton vm" + .left + = form_tag search_project_issues_path(@project), :method => :get, :remote => true do + = search_field_tag :issue_search, nil, { :placeholder => 'Search', :class => 'issue_search' } + = link_to 'New Issue', new_project_issue_path(@project), :remote => true, :class => "lbutton vm" + .right = form_tag project_issues_path(@project), :method => :get do .span-2 @@ -20,6 +24,18 @@ #issues-table-holder= render "issues" %br :javascript + $('.issue_search').keyup(function() { + var terms = $(this).val(); + var project_id = 1; + + if (terms.length >= 2) { + $.get($(this).parent().attr('action'), { 'terms': terms, project: project_id }, function(response) { + $('#issues-table').html(response); + setSortable(); + }); + } + }); + $('.delete-issue').live('ajax:success', function() { $(this).closest('tr').fadeOut(); }); diff --git a/config/database.yml b/config/database.yml index 51a4dd45..59e1f12c 100644 --- a/config/database.yml +++ b/config/database.yml @@ -4,8 +4,9 @@ # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' development: - adapter: sqlite3 - database: db/development.sqlite3 + adapter: mysql2 + database: gitlab_development + username: root pool: 5 timeout: 5000 @@ -13,13 +14,11 @@ development: # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: sqlite3 - database: db/test.sqlite3 - pool: 5 - timeout: 5000 + adapter: mysql2 + database: gitlab_development + username: root production: - adapter: sqlite3 - database: db/production.sqlite3 - pool: 5 - timeout: 5000 + adatper: mysql2 + database: gitlab_test + username: root diff --git a/config/routes.rb b/config/routes.rb index 8a40a8fe..57879224 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -47,6 +47,9 @@ Gitlab::Application.routes.draw do collection do post :sort end + collection do + get :search + end end resources :notes, :only => [:create, :destroy] end diff --git a/spec/requests/issues_spec.rb b/spec/requests/issues_spec.rb index 79fdf5ef..d3582d16 100644 --- a/spec/requests/issues_spec.rb +++ b/spec/requests/issues_spec.rb @@ -144,4 +144,26 @@ describe "Issues" do end end end + + describe "Search issue", :js => true do + before do + ['foobar', 'foobar2', 'gitlab'].each do |title| + @issue = Factory :issue, + :author => @user, + :assignee => @user, + :project => project, + :title => title + @issue.save + end + end + + it "should search and return the correct results" do + visit project_issues_path(project) + fill_in "issue_search", :with => "foobar" + page.should have_content 'foobar' + page.should have_content 'foobar2' + page.should_not have_content 'gitlab' + end + end + end From 6d6eefa0e201953818592962b723c3ee4e5d0c5a Mon Sep 17 00:00:00 2001 From: VSizov Date: Sat, 22 Oct 2011 13:50:02 +0300 Subject: [PATCH 082/176] fix remove repo --- lib/gitosis.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitosis.rb b/lib/gitosis.rb index 59b3f2a2..1dd87c0a 100644 --- a/lib/gitosis.rb +++ b/lib/gitosis.rb @@ -42,7 +42,7 @@ class Gitosis end def destroy_project(project) - `rm -Rf #{project.path_to_repo}` + `sudo -u git rm -Rf #{project.path_to_repo}` conf = IniFile.new(File.join(@local_dir,'gitosis','gitosis.conf')) From c7ccfb9a9d639ab172beaa319db09b343c65168f Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Sat, 22 Oct 2011 14:07:09 +0300 Subject: [PATCH 083/176] low case --- lib/gitosis.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitosis.rb b/lib/gitosis.rb index 1dd87c0a..92d32d8b 100644 --- a/lib/gitosis.rb +++ b/lib/gitosis.rb @@ -42,7 +42,7 @@ class Gitosis end def destroy_project(project) - `sudo -u git rm -Rf #{project.path_to_repo}` + `sudo -u git rm -rf #{project.path_to_repo}` conf = IniFile.new(File.join(@local_dir,'gitosis','gitosis.conf')) From c66c30c821a77309302560667692854b2caabb8d Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 20 Oct 2011 09:48:09 -0400 Subject: [PATCH 084/176] Add check to ensure that a team member has atleast one Access Role selected --- app/models/users_project.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/models/users_project.rb b/app/models/users_project.rb index bdc10633..96e2d16a 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -9,7 +9,8 @@ class UsersProject < ActiveRecord::Base validates_uniqueness_of :user_id, :scope => [:project_id] validates_presence_of :user_id validates_presence_of :project_id - + validate :user_has_a_role_selected + delegate :name, :email, :to => :user, :prefix => true def update_gitosis_project @@ -18,6 +19,10 @@ class UsersProject < ActiveRecord::Base end end + def user_has_a_role_selected + errors.add(:base, "Please choose at least one Role in the Access list") unless read || write || admin + end + end # == Schema Information # From 977fe7307320ccd7613ea97823b68ab356ebbe60 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 09:58:28 +0300 Subject: [PATCH 085/176] prepare for 1.1 --- CHANGELOG | 2 ++ VERSION | 2 +- update.rb | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index aa846166..96acfba1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,6 @@ v 1.1.0 + - project dashboard + - wall redesigned - feature: code snippets - fixed horizontal scroll on file preview - fixed app crash if commit message has invalid chars diff --git a/VERSION b/VERSION index 6d7de6e6..9084fa2f 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.2 +1.1.0 diff --git a/update.rb b/update.rb index dccb7df3..b81a4088 100644 --- a/update.rb +++ b/update.rb @@ -19,8 +19,8 @@ env = if envs.include?(ARGV[0]) puts yellow "== RAILS ENV | #{env}" current_version = version puts yellow "Your version is #{current_version}" -puts yellow "Check for new version: $ git pull origin" -`git pull origin` # pull from origin +puts yellow "Check for new version: $ git pull origin 1x" +`git pull origin 1x` # pull from origin # latest version if version == current_version From 24f04c0a6154c6d5890642fb8a8ec16b44146547 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 14:03:34 +0300 Subject: [PATCH 086/176] recent radio button --- app/controllers/projects_controller.rb | 32 ++++++++++++-------------- app/models/note.rb | 1 + app/models/project.rb | 28 ++++++++++++++++++++++ app/views/projects/show.html.haml | 7 ++++-- app/views/projects/wall.html.haml | 5 +++- spec/requests/projects_spec.rb | 2 +- 6 files changed, 54 insertions(+), 21 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index dc94bae2..5ccfe4bb 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -60,24 +60,21 @@ class ProjectsController < ApplicationController end def show - if @project.repo_exists? - @date = case params[:view] - when "week" then Date.today - 7.days - else Date.today - end.at_beginning_of_day + return render "projects/empty" unless @project.repo_exists? + @date = case params[:view] + when "week" then Date.today - 7.days + when "day" then Date.today + else nil + end - @heads = @project.repo.heads - @commits = @heads.map do |h| - @project.repo.log(h.name, nil, :since => @date) - end.flatten.uniq { |c| c.id } - - @commits.sort! do |x, y| - y.committed_date <=> x.committed_date - end + if @date + @date = @date.at_beginning_of_day + @commits = @project.commits_since(@date) @messages = project.notes.since(@date).order("created_at DESC") - else - return render "projects/empty" + else + @commits = @project.fresh_commits + @messages = project.notes.fresh.limit(10) end end @@ -89,11 +86,12 @@ class ProjectsController < ApplicationController @date = case params[:view] when "week" then Date.today - 7.days when "all" then nil - else Date.today + when "day" then Date.today + else nil end @notes = @project.common_notes.order("created_at DESC") - @notes = @notes.since(@date.at_beginning_of_day) if @date + @notes = @date ? @notes.since(@date.at_beginning_of_day) : @notes.fresh.limit(10) @note = Note.new end diff --git a/app/models/note.rb b/app/models/note.rb index 71fd9dcd..e3dabce4 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -24,6 +24,7 @@ class Note < ActiveRecord::Base scope :last_week, where("created_at >= :date", :date => (Date.today - 7.days)) scope :since, lambda { |day| where("created_at >= :date", :date => (day)) } + scope :fresh, order("created_at DESC") mount_uploader :attachment, AttachmentUploader end diff --git a/app/models/project.rb b/app/models/project.rb index f51bd9b3..d70b18e7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -126,6 +126,34 @@ class Project < ActiveRecord::Base end end + def heads + @heads ||= repo.heads + end + + def fresh_commits + commits = heads.map do |h| + repo.commits(h.name, 10) + end.flatten.uniq { |c| c.id } + + commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end + + commits[0..10] + end + + def commits_since(date) + commits = heads.map do |h| + repo.log(h.name, nil, :since => date) + end.flatten.uniq { |c| c.id } + + commits.sort! do |x, y| + y.committed_date <=> x.committed_date + end + + commits + end + def tree(fcommit, path = nil) fcommit = commit if fcommit == :head tree = fcommit.tree diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index ff6078c1..85019ecb 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -1,9 +1,12 @@ %div - %h2.left Recent history + %h2.left History .right = form_tag project_path(@project), :method => :get do .span-2 - = radio_button_tag :view, "day", (params[:view] || "day") == "day", :onclick => "this.form.submit()", :id => "day_view" + = radio_button_tag :view, "recent", (params[:view] || "recent") == "recent", :onclick => "this.form.submit()", :id => "recent_view" + = label_tag "recent_view","Recent" + .span-2 + = radio_button_tag :view, "day", params[:view] == "day", :onclick => "this.form.submit()", :id => "day_view" = label_tag "day_view","Today" .span-2 = radio_button_tag :view, "week", params[:view] == "week", :onclick => "this.form.submit()", :id => "week_view" diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml index d3dcb353..ed22478c 100644 --- a/app/views/projects/wall.html.haml +++ b/app/views/projects/wall.html.haml @@ -4,7 +4,10 @@ .right = form_tag wall_project_path(@project), :method => :get do .span-2 - = radio_button_tag :view, "day", (params[:view] || "day") == "day", :onclick => "this.form.submit()", :id => "day_view" + = radio_button_tag :view, "recent", (params[:view] || "recent") == "recent", :onclick => "this.form.submit()", :id => "recent_view" + = label_tag "recent_view","Recent" + .span-2 + = radio_button_tag :view, "day", params[:view] == "day", :onclick => "this.form.submit()", :id => "day_view" = label_tag "day_view","Today" .span-2 = radio_button_tag :view, "week", params[:view] == "week", :onclick => "this.form.submit()", :id => "week_view" diff --git a/spec/requests/projects_spec.rb b/spec/requests/projects_spec.rb index a1bac062..945c1ea2 100644 --- a/spec/requests/projects_spec.rb +++ b/spec/requests/projects_spec.rb @@ -73,7 +73,7 @@ describe "Projects" do end it "should beahave like dashboard" do - page.should have_content("Recent history") + page.should have_content("History") end end From d49645a01348e093b87586b3575e93233d497aea Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 14:25:42 +0300 Subject: [PATCH 087/176] fixed wall --all option --- app/controllers/projects_controller.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 5ccfe4bb..54d19af7 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -83,16 +83,15 @@ class ProjectsController < ApplicationController # def wall - @date = case params[:view] - when "week" then Date.today - 7.days - when "all" then nil - when "day" then Date.today - else nil - end - - @notes = @project.common_notes.order("created_at DESC") - @notes = @date ? @notes.since(@date.at_beginning_of_day) : @notes.fresh.limit(10) @note = Note.new + @notes = @project.common_notes.order("created_at DESC") + + @notes = case params[:view] + when "week" then @notes.since((Date.today - 7.days).at_beginning_of_day) + when "all" then @notes.all + when "day" then @notes.since(Date.today.at_beginning_of_day) + else @notes.fresh.limit(10) + end end # From b3279b9b5170a19a2aa504eae94a9a8be5908755 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 15:35:42 +0300 Subject: [PATCH 088/176] moved from albino -> pygments.rb --- Gemfile | 2 +- Gemfile.lock | 15 +++++++-------- app/models/snippet.rb | 3 +-- app/views/projects/_tree_file.html.haml | 1 + app/views/projects/empty.html.erb | 7 ++++--- config/initializers/grit_ext.rb | 2 +- lib/utils.rb | 8 ++++++-- 7 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Gemfile b/Gemfile index 523793e7..77a00659 100644 --- a/Gemfile +++ b/Gemfile @@ -15,7 +15,7 @@ gem 'therubyracer' gem 'faker' gem 'seed-fu', :git => 'git://github.com/mbleigh/seed-fu.git' gem "inifile" -gem "albino", :git => "git://github.com/gitlabhq/albino.git" +gem "pygments.rb", "0.2.3" gem "kaminari" gem "thin" gem "git" diff --git a/Gemfile.lock b/Gemfile.lock index 2aa894aa..5ba34459 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -4,13 +4,6 @@ GIT specs: annotate (2.4.1.beta1) -GIT - remote: git://github.com/gitlabhq/albino.git - revision: 118380924969f3a856659f86ea1f40c1ba7bfcb1 - specs: - albino (1.3.3) - posix-spawn (>= 0.3.6) - GIT remote: git://github.com/gitlabhq/grit.git revision: ff015074ef35bd94cba943f9c0f98e161ab5851c @@ -72,6 +65,7 @@ GEM ZenTest (= 4.5) awesome_print (0.4.0) bcrypt-ruby (3.0.1) + blankslate (2.1.2.4) builder (3.0.0) capybara (1.0.1) mime-types (>= 1.16) @@ -138,6 +132,8 @@ GEM orm_adapter (0.0.5) polyglot (0.3.2) posix-spawn (0.3.6) + pygments.rb (0.2.3) + rubypython (>= 0.5.1) rack (1.3.2) rack-cache (1.0.3) rack (>= 0.4) @@ -189,6 +185,9 @@ GEM ruby-debug-base19 (>= 0.11.19) ruby_core_source (0.1.5) archive-tar-minitar (>= 0.5.2) + rubypython (0.5.1) + blankslate (>= 2.1.2.3) + ffi (~> 1.0.7) rubyzip (0.9.4) sass (3.1.7) sass-rails (3.1.1) @@ -242,7 +241,6 @@ PLATFORMS DEPENDENCIES acts_as_list - albino! annotate! autotest autotest-rails @@ -260,6 +258,7 @@ DEPENDENCIES jquery-rails kaminari launchy + pygments.rb (= 0.2.3) rails (= 3.1.0) rails-footnotes (>= 3.7.5.rc4) rspec-rails diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 119b69a4..95d6a07d 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -32,8 +32,7 @@ class Snippet < ActiveRecord::Base end def colorize - ft = handle_file_type(file_name) - Albino.colorize(content, ft, :html, 'utf-8', "linenos=True") + system_colorize(content, file_name) end end # == Schema Information diff --git a/app/views/projects/_tree_file.html.haml b/app/views/projects/_tree_file.html.haml index ae95d483..41a2287a 100644 --- a/app/views/projects/_tree_file.html.haml +++ b/app/views/projects/_tree_file.html.haml @@ -1,3 +1,4 @@ +:css .view_file .view_file_header %strong diff --git a/app/views/projects/empty.html.erb b/app/views/projects/empty.html.erb index a8917471..4c60facd 100644 --- a/app/views/projects/empty.html.erb +++ b/app/views/projects/empty.html.erb @@ -1,3 +1,4 @@ +<% bash_lexer = Pygments::Lexer[:bash] %>

      Git global setup:

      @@ -6,7 +7,7 @@ git config --global user.name "#{current_user.name}" git config --global user.email "#{current_user.email}" eos %> - <%= raw Albino.colorize(setup_str, :bash) %> + <%= raw bash_lexer.highlight(setup_str) %>

      Next steps:

      @@ -21,7 +22,7 @@ git remote add origin #{@project.url_to_repo} git push -u origin master eos %> - <%= raw Albino.colorize(repo_setup_str, :bash) %> + <%= raw bash_lexer.highlight(repo_setup_str) %>

      Existing Git Repo?

      @@ -31,7 +32,7 @@ git remote add origin #{@project.url_to_repo} git push -u origin master eos %> - <%= raw Albino.colorize(exist_repo_setup_str, :bash) %> + <%= raw bash_lexer.highlight(exist_repo_setup_str) %>

      Remove this project?

      diff --git a/config/initializers/grit_ext.rb b/config/initializers/grit_ext.rb index 8f1329a6..4bd71003 100644 --- a/config/initializers/grit_ext.rb +++ b/config/initializers/grit_ext.rb @@ -1,5 +1,5 @@ require 'grit' -require 'albino' +require 'pygments' require "utils" Grit::Blob.class_eval do diff --git a/lib/utils.rb b/lib/utils.rb index 40bf2673..e57121a3 100644 --- a/lib/utils.rb +++ b/lib/utils.rb @@ -18,8 +18,12 @@ module Utils module Colorize def colorize - ft = handle_file_type(name, mime_type) - Albino.colorize(data, ft, :html, 'utf-8', "linenos=True") + system_colorize(data, name) + end + + def system_colorize(data, file_name) + ft = handle_file_type(file_name) + Pygments.highlight(data, :lexer => ft, :options => { :encoding => 'utf-8', :linenos => 'True' }) end def handle_file_type(file_name, mime_type = nil) From 9fa4df16ec8f8317c83371c5768c30e276e49ae9 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 15:56:37 +0300 Subject: [PATCH 089/176] now you can view comrade profile info #134 --- app/views/projects/_top_menu.html.haml | 2 +- app/views/team_members/_show.html.haml | 6 ++-- app/views/team_members/show.html.haml | 28 +++++++++++++++++++ ...021101550_change_social_fields_in_users.rb | 10 +++++++ db/schema.rb | 8 +++--- spec/requests/team_members_spec.rb | 9 ++++++ spec/support/login.rb | 3 +- 7 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 app/views/team_members/show.html.haml create mode 100644 db/migrate/20111021101550_change_social_fields_in_users.rb diff --git a/app/views/projects/_top_menu.html.haml b/app/views/projects/_top_menu.html.haml index e281b93b..59f2533e 100644 --- a/app/views/projects/_top_menu.html.haml +++ b/app/views/projects/_top_menu.html.haml @@ -5,7 +5,7 @@ %span= link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil %span= link_to "Commits", project_commits_path(@project), :class => current_page?(:controller => "commits", :action => "index", :project_id => @project) ? "current" : nil %span - = link_to team_project_path(@project), :class => current_page?(:controller => "projects", :action => "team", :id => @project) ? "current" : nil do + = link_to team_project_path(@project), :class => (current_page?(:controller => "projects", :action => "team", :id => @project) || controller.controller_name == "team_members") ? "current" : nil do Team - if @project.users_projects.count > 0 %span{ :class => "top_menu_count" }= @project.users_projects.count diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml index 6d310768..b9a68e6c 100644 --- a/app/views/team_members/_show.html.haml +++ b/app/views/team_members/_show.html.haml @@ -1,8 +1,10 @@ - user = member.user %tr{:id => dom_id(member)} %td - = image_tag gravatar_icon(user.email), :class => "left", :width => 40, :style => "padding:0 5px;" - = truncate user.name, :lenght => 16 + = link_to image_tag(gravatar_icon(user.email), :class => "left", :width => 40, :style => "padding:0 5px;"), project_team_member_path(@project, member) + + = link_to truncate(user.name, :lenght => 16), project_team_member_path(@project, member) + %td= truncate user.email, :lenght => 16 - if can? current_user, :admin_project, @project = form_for(member, :as => :team_member, :url => project_team_member_path(@project, member)) do |f| diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml new file mode 100644 index 00000000..d07c54f8 --- /dev/null +++ b/app/views/team_members/show.html.haml @@ -0,0 +1,28 @@ +- user = @team_member.user +.span-2 + = image_tag gravatar_icon(user.email), :class => "left", :width => 60, :style => "padding-right:5px;" +%p + %b Name: + = user.name +%p + %b Email: + = user.email + +%br + +- unless user.skype.empty? + .div + %b Skype: + = user.skype + +- unless user.linkedin.empty? + .div + %b LinkedIn: + = user.linkedin + +- unless user.twitter.empty? + .div + %b Twitter: + = user.twitter + + diff --git a/db/migrate/20111021101550_change_social_fields_in_users.rb b/db/migrate/20111021101550_change_social_fields_in_users.rb new file mode 100644 index 00000000..6f05c05d --- /dev/null +++ b/db/migrate/20111021101550_change_social_fields_in_users.rb @@ -0,0 +1,10 @@ +class ChangeSocialFieldsInUsers < ActiveRecord::Migration + def up + change_column(:users, :skype, :string, {:null => false, :default => ''}) + change_column(:users, :linkedin, :string, {:null => false, :default => ''}) + change_column(:users, :twitter, :string, {:null => false, :default => ''}) + end + + def down + end +end diff --git a/db/schema.rb b/db/schema.rb index 6408792f..cc805990 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111019212429) do +ActiveRecord::Schema.define(:version => 20111021101550) do create_table "issues", :force => true do |t| t.string "title" @@ -82,9 +82,9 @@ ActiveRecord::Schema.define(:version => 20111019212429) do t.string "name" t.boolean "admin", :default => false, :null => false t.integer "projects_limit", :default => 10 - t.string "skype" - t.string "linkedin" - t.string "twitter" + t.string "skype", :default => "", :null => false + t.string "linkedin", :default => "", :null => false + t.string "twitter", :default => "", :null => false end add_index "users", ["email"], :name => "index_users_on_email", :unique => true diff --git a/spec/requests/team_members_spec.rb b/spec/requests/team_members_spec.rb index db7513ae..dd92febf 100644 --- a/spec/requests/team_members_spec.rb +++ b/spec/requests/team_members_spec.rb @@ -7,6 +7,15 @@ describe "TeamMembers" do @project.add_access(@user, :read, :admin) end + describe "View profile" do + it "should be available" do + visit(team_project_path(@project)) + find(:xpath, "//table[@id='team-table']//a[1]").click + page.should have_content @user.skype + page.should_not have_content 'Twitter' + end + end + describe "New Team member", :js => true do before do @user_1 = Factory :user diff --git a/spec/support/login.rb b/spec/support/login.rb index 09f64f9e..462647ab 100644 --- a/spec/support/login.rb +++ b/spec/support/login.rb @@ -3,7 +3,8 @@ module LoginMacros @user = User.create(:email => "user#{User.count}@mail.com", :name => "John Smith", :password => "123456", - :password_confirmation => "123456") + :password_confirmation => "123456", + :skype => 'user_skype') if role == :admin @user.admin = true From 1c2660729003932183ec6c7973e4ee15192f99d7 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 16:36:33 +0300 Subject: [PATCH 090/176] corrected last migration --- .../20111021101550_change_social_fields_in_users.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/db/migrate/20111021101550_change_social_fields_in_users.rb b/db/migrate/20111021101550_change_social_fields_in_users.rb index 6f05c05d..6e506c1c 100644 --- a/db/migrate/20111021101550_change_social_fields_in_users.rb +++ b/db/migrate/20111021101550_change_social_fields_in_users.rb @@ -1,8 +1,12 @@ class ChangeSocialFieldsInUsers < ActiveRecord::Migration def up - change_column(:users, :skype, :string, {:null => false, :default => ''}) - change_column(:users, :linkedin, :string, {:null => false, :default => ''}) - change_column(:users, :twitter, :string, {:null => false, :default => ''}) + remove_column :users, :skype + remove_column :users, :linkedin + remove_column :users, :twitter + + add_column :users, :skype, :string, {:null => false, :default => ''} + add_column :users, :linkedin, :string, {:null => false, :default => ''} + add_column :users, :twitter, :string, {:null => false, :default => ''} end def down From 35d24b3928a0905d23e8e33bbc9a89d33fa0a480 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 20:58:04 +0300 Subject: [PATCH 091/176] cleaning --- README.rdoc | 8 +++-- db/fixtures/development/001_admin.rb | 10 ++++++- db/fixtures/production/001_admin.rb | 9 ++++++ install.rb | 32 -------------------- update.rb | 44 ---------------------------- 5 files changed, 23 insertions(+), 80 deletions(-) delete mode 100644 install.rb delete mode 100644 update.rb diff --git a/README.rdoc b/README.rdoc index 5e47b269..3e604a0f 100644 --- a/README.rdoc +++ b/README.rdoc @@ -36,18 +36,19 @@ sqlite as default db echo "gitlabhq ALL = (git) NOPASSWD: /bin/rm" | sudo tee -a /etc/sudoers sudo gem install bundler + bundle - RAILS_ENV=production rake db:setup + bundle exec rake db:setup RAILS_ENV=production # create admin user # login....admin@local.host # pass.....5iveL!fe - RAILS_ENV=production rake db:seed_fu + bundle exec rake db:seed_fu RAILS_ENV=production Install gitosis, edit conf/gitosis.yml & start server - rails s + rails s -e production == Install Gitosis sudo aptitude install gitosis @@ -65,6 +66,7 @@ Install gitosis, edit conf/gitosis.yml & start server ssh-keygen -t rsa sudo -H -u git gitosis-init < ~/.ssh/id_rsa.pub + sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update diff --git a/db/fixtures/development/001_admin.rb b/db/fixtures/development/001_admin.rb index 9c5a6da0..cfff6bf8 100644 --- a/db/fixtures/development/001_admin.rb +++ b/db/fixtures/development/001_admin.rb @@ -1,4 +1,3 @@ -# Admin account admin = User.create( :email => "admin@local.host", :name => "Administrator", @@ -9,3 +8,12 @@ admin = User.create( admin.projects_limit = 10000 admin.admin = true admin.save! + +if admin.valid? +puts %q[ +Administrator account created: + +login.........admin@local.host +password......5iveL!fe +] +end diff --git a/db/fixtures/production/001_admin.rb b/db/fixtures/production/001_admin.rb index 94d1abe8..cfff6bf8 100644 --- a/db/fixtures/production/001_admin.rb +++ b/db/fixtures/production/001_admin.rb @@ -8,3 +8,12 @@ admin = User.create( admin.projects_limit = 10000 admin.admin = true admin.save! + +if admin.valid? +puts %q[ +Administrator account created: + +login.........admin@local.host +password......5iveL!fe +] +end diff --git a/install.rb b/install.rb deleted file mode 100644 index a118cb5d..00000000 --- a/install.rb +++ /dev/null @@ -1,32 +0,0 @@ -root_path = File.expand_path(File.dirname(__FILE__)) -require File.join(root_path, "lib", "color") -include Color - -# -# ruby ./update.rb development # or test or production (default) -# -envs = ["production", "test", "development"] -env = if envs.include?(ARGV[0]) - ARGV[0] - else - "production" - end - -puts green " == Install for ENV=#{env} ..." - -# bundle install -`bundle install` - -# migrate db -`bundle exec rake db:create RAILS_ENV=#{env}` -`bundle exec rake db:schema:load RAILS_ENV=#{env}` -`bundle exec rake db:seed_fu RAILS_ENV=#{env}` - -puts green %q[ -Administrator account created: - -login.........admin@local.host -password......5iveL!fe -] - -puts green " == Done! Now you can start server" diff --git a/update.rb b/update.rb deleted file mode 100644 index b81a4088..00000000 --- a/update.rb +++ /dev/null @@ -1,44 +0,0 @@ -root_path = File.expand_path(File.dirname(__FILE__)) -require File.join(root_path, "lib", "color") -include Color - -def version - File.read("VERSION") -end - -# -# ruby ./update.rb development # or test or production (default) -# -envs = ["production", "test", "development"] -env = if envs.include?(ARGV[0]) - ARGV[0] - else - "production" - end - -puts yellow "== RAILS ENV | #{env}" -current_version = version -puts yellow "Your version is #{current_version}" -puts yellow "Check for new version: $ git pull origin 1x" -`git pull origin 1x` # pull from origin - -# latest version -if version == current_version - puts yellow "You have a latest version" -else - puts green "Update to #{version}" - -`bundle install` - - # migrate db -if env == "development" -`bundle exec rake db:migrate RAILS_ENV=development` -`bundle exec rake db:migrate RAILS_ENV=test` -else -`bundle exec rake db:migrate RAILS_ENV=#{env}` -end - - puts green "== Done! Now you can start/restart server" -end - - From 29e11d1461a5689ff295adb035e38564701ad377 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 21:14:55 +0300 Subject: [PATCH 092/176] link to file for commit diff --- app/views/commits/_diff.html.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/commits/_diff.html.haml b/app/views/commits/_diff.html.haml index 73652aaf..c88e5430 100644 --- a/app/views/commits/_diff.html.haml +++ b/app/views/commits/_diff.html.haml @@ -31,7 +31,8 @@ - if diff.deleted_file %strong{:id => "#{diff.b_path}"}= diff.a_path - else - %strong{:id => "#{diff.b_path}"}= diff.b_path + = link_to tree_file_project_path(@project, @commit.id, diff.b_path) do + %strong{:id => "#{diff.b_path}"}= diff.b_path %br/ .diff_file_content - if file.text? From 1a9531c9a42e380d922de98ad1658e85ac5fbde6 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 21:40:36 +0300 Subject: [PATCH 093/176] fix #140, commit lil refactor --- app/models/project.rb | 8 +++++ app/views/commits/_diff.html.haml | 41 ++------------------------ app/views/commits/_diff_head.html.haml | 24 +++++++++++++++ app/views/commits/_text_file.html.haml | 15 ++++++++++ spec/models/project_spec.rb | 9 ++++++ 5 files changed, 59 insertions(+), 38 deletions(-) create mode 100644 app/views/commits/_diff_head.html.haml create mode 100644 app/views/commits/_text_file.html.haml diff --git a/app/models/project.rb b/app/models/project.rb index d70b18e7..1dd04e1f 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -36,6 +36,8 @@ class Project < ActiveRecord::Base validate :check_limit + validate :repo_name + after_destroy :destroy_gitosis_project after_save :update_gitosis_project @@ -168,6 +170,12 @@ class Project < ActiveRecord::Base errors[:base] << ("Cant check your ability to create project") end + def repo_name + if path == "gitosis-admin" + errors.add(:path, "Project path like 'gitosis-admin' is not allowed") + end + end + def valid_repo? repo rescue diff --git a/app/views/commits/_diff.html.haml b/app/views/commits/_diff.html.haml index c88e5430..2807e090 100644 --- a/app/views/commits/_diff.html.haml +++ b/app/views/commits/_diff.html.haml @@ -1,27 +1,5 @@ -.file_stats - - @commit.diffs.each do |diff| - - if diff.deleted_file - %span.removed_file - %a{:href => "##{diff.a_path}"} - = diff.a_path - = image_tag "blueprint_delete.png" - - elsif diff.renamed_file - %span.moved_file - %a{:href => "##{diff.b_path}"} - = diff.a_path - = "->" - = diff.b_path - = image_tag "blueprint_notice.png" - - elsif diff.new_file - %span.new_file - %a{:href => "##{diff.b_path}"} - = diff.b_path - = image_tag "blueprint_add.png" - - else - %span.edit_file - %a{:href => "##{diff.b_path}"} - = diff.b_path - = image_tag "blueprint_info.png" +.file_stats= render "commits/diff_head" + - @commit.diffs.each do |diff| - next if diff.diff.empty? - file = (@commit.tree / diff.b_path) @@ -36,20 +14,7 @@ %br/ .diff_file_content - if file.text? - - lines_arr = diff.diff.lines.to_a - - line_old = lines_arr[2].match(/-(\d)/)[0].to_i.abs rescue 0 - - line_new = lines_arr[2].match(/\+(\d)/)[0].to_i.abs rescue 0 - - lines = lines_arr[3..-1].join - - lines.each_line do |line| - = diff_line(line, line_new, line_old) - - if line[0] == "+" - - line_new += 1 - - elsif - - line[0] == "-" - - line_old += 1 - - else - - line_new += 1 - - line_old += 1 + = render :partial => "commits/text_file", :locals => { :diff => diff } - elsif file.image? .diff_file_content_image %img{:src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} diff --git a/app/views/commits/_diff_head.html.haml b/app/views/commits/_diff_head.html.haml new file mode 100644 index 00000000..922c3599 --- /dev/null +++ b/app/views/commits/_diff_head.html.haml @@ -0,0 +1,24 @@ +- @commit.diffs.each do |diff| + - if diff.deleted_file + %span.removed_file + %a{:href => "##{diff.a_path}"} + = diff.a_path + = image_tag "blueprint_delete.png" + - elsif diff.renamed_file + %span.moved_file + %a{:href => "##{diff.b_path}"} + = diff.a_path + = "->" + = diff.b_path + = image_tag "blueprint_notice.png" + - elsif diff.new_file + %span.new_file + %a{:href => "##{diff.b_path}"} + = diff.b_path + = image_tag "blueprint_add.png" + - else + %span.edit_file + %a{:href => "##{diff.b_path}"} + = diff.b_path + = image_tag "blueprint_info.png" + diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml new file mode 100644 index 00000000..b20aa8af --- /dev/null +++ b/app/views/commits/_text_file.html.haml @@ -0,0 +1,15 @@ +- lines_arr = diff.diff.lines.to_a +- line_old = lines_arr[2].match(/-(\d)/)[0].to_i.abs rescue 0 +- line_new = lines_arr[2].match(/\+(\d)/)[0].to_i.abs rescue 0 +- lines = lines_arr[3..-1].join +- lines.each_line do |line| + = diff_line(line, line_new, line_old) + - if line[0] == "+" + - line_new += 1 + - elsif + - line[0] == "-" + - line_old += 1 + - else + - line_new += 1 + - line_old += 1 + diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 6ed8653d..0c62743d 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -4,11 +4,15 @@ describe Project do describe "Associations" do it { should have_many(:users) } it { should have_many(:users_projects) } + it { should have_many(:issues) } + it { should have_many(:notes) } + it { should have_many(:snippets) } end describe "Validation" do it { should validate_presence_of(:name) } it { should validate_presence_of(:path) } + it { should validate_presence_of(:code) } end describe "Respond to" do @@ -31,6 +35,11 @@ describe Project do it { should respond_to(:commit) } end + it "should not allow 'gitosis-admin' as repo name" do + should allow_value("blah").for(:path) + should_not allow_value("gitosis-admin").for(:path) + end + it "should return valid url to repo" do project = Project.new(:path => "somewhere") project.url_to_repo.should == "git@localhost:somewhere.git" From 72d15cc7caf7e457a578d13b496b6b461487f1fc Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 21:51:55 +0300 Subject: [PATCH 094/176] error fields highlight --- app/assets/stylesheets/projects.css.scss | 9 +++++++++ app/models/project.rb | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 51788672..8caa2810 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -638,3 +638,12 @@ tbody tr:nth-child(2n) td, tbody tr.even td { display:none; } } + +.field_with_errors { + input[type="text"], + input[type="password"], + textarea + { + background: none repeat scroll 0 0 #FFBBBB + } +} diff --git a/app/models/project.rb b/app/models/project.rb index 1dd04e1f..5262e552 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -35,7 +35,6 @@ class Project < ActiveRecord::Base :presence => true validate :check_limit - validate :repo_name after_destroy :destroy_gitosis_project @@ -172,7 +171,7 @@ class Project < ActiveRecord::Base def repo_name if path == "gitosis-admin" - errors.add(:path, "Project path like 'gitosis-admin' is not allowed") + errors.add(:path, " like 'gitosis-admin' is not allowed") end end From 00290b9214e4dc4688e93c04489a7551da697ee6 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 21 Oct 2011 22:44:08 +0300 Subject: [PATCH 095/176] test cov --- app/controllers/team_members_controller.rb | 28 ++++++---------------- spec/requests/team_members_spec.rb | 26 ++++++++++++++++---- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb index 5fb2710d..84addf8d 100644 --- a/app/controllers/team_members_controller.rb +++ b/app/controllers/team_members_controller.rb @@ -8,35 +8,16 @@ class TeamMembersController < ApplicationController def show @team_member = project.users_projects.find(params[:id]) - - respond_to do |format| - format.html # show.html.erb - format.js - end end def new @team_member = project.users_projects.new - - respond_to do |format| - format.html # new.html.erb - format.js - end end def create @team_member = UsersProject.new(params[:team_member]) @team_member.project = project - - respond_to do |format| - if @team_member.save - format.html { redirect_to @team_member, notice: 'Team member was successfully created.' } - format.js - else - format.html { render action: "new" } - format.js - end - end + @team_member.save end def update @@ -45,7 +26,12 @@ class TeamMembersController < ApplicationController respond_to do |format| format.js - format.html { redirect_to team_project_path(@project)} + format.html do + unless @team_member.valid? + flash[:alert] = "User should have at least one role" + end + redirect_to team_project_path(@project) + end end end diff --git a/spec/requests/team_members_spec.rb b/spec/requests/team_members_spec.rb index dd92febf..ec0af321 100644 --- a/spec/requests/team_members_spec.rb +++ b/spec/requests/team_members_spec.rb @@ -29,19 +29,37 @@ describe "TeamMembers" do describe "fill in" do before do - check "team_member_read" click_link "Select user" click_link @user_1.name - #select @user_1.name, :from => "team_member_user_id" + + within "#team_member_new" do + check "team_member_read" + check "team_member_write" + end end - it { expect { click_button "Save" }.to change {UsersProject.count}.by(1) } + it { expect { click_button "Save";sleep(1) }.to change {UsersProject.count}.by(1) } it "should add new member to table" do click_button "Save" + @member = UsersProject.last - page.should_not have_content("Add new member") page.should have_content @user_1.name + + @member.read.should be_true + @member.write.should be_true + @member.admin.should be_false + end + + it "should not allow creation without access selected" do + within "#team_member_new" do + uncheck "team_member_read" + uncheck "team_member_write" + uncheck "team_member_admin" + end + + expect { click_button "Save" }.to_not change {UsersProject.count} + page.should have_content("Please choose at least one Role in the Access list") end end end From edeb20e95bd26a08b10f211b33fb5bedce9b9957 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Sat, 22 Oct 2011 14:48:10 +0300 Subject: [PATCH 096/176] readme for v1.1.0 --- README.rdoc | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.rdoc b/README.rdoc index 3e604a0f..4016ebba 100644 --- a/README.rdoc +++ b/README.rdoc @@ -28,12 +28,18 @@ sqlite as default db git clone git://github.com/gitlabhq/gitlabhq.git + cd gitlabhq/ # install this library first sudo easy_install pygments - - echo "gitlabhq ALL = (git) NOPASSWD: /bin/rm" | sudo tee -a /etc/sudoers + + # give your user access to remove git repo + # Ex. + # If you are going to use user 'gitlabhq' for rails server + # gitlabhq ALL = (git) NOPASSWD: /bin/rm" | sudo tee -a /etc/sudoers + # + echo "USERNAME ALL = (git) NOPASSWD: /bin/rm" | sudo tee -a /etc/sudoers sudo gem install bundler @@ -87,3 +93,8 @@ Install gitosis, edit conf/gitosis.yml & start server echo "gem: --no-rdoc --no-ri" > ~/.gemrc + +== Contribute + +We develop project on our private server. +Want to help? Contact us on twitter or email to become a team member. From 61e6751ea676d23f5ef88de6d0bf9c273f785516 Mon Sep 17 00:00:00 2001 From: Sairam Kunala Date: Sun, 23 Oct 2011 12:47:57 +0530 Subject: [PATCH 097/176] bug fix: history in commit history not working as expected for tags and branches --- app/views/projects/_tree.html.haml | 8 ++++---- app/views/projects/_tree_file.html.haml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/views/projects/_tree.html.haml b/app/views/projects/_tree.html.haml index d1903586..11b04a3b 100644 --- a/app/views/projects/_tree.html.haml +++ b/app/views/projects/_tree.html.haml @@ -30,15 +30,15 @@ %th Last Update %th Last commit - = link_to "history", project_commits_path(@project, :path => params[:path]), :class => "right" + = link_to "history", project_commits_path(@project, :path => params[:path], :branch => params[:branch],:tag => params[:tag]), :class => "right" - if params[:path] - file = File.join(params[:path], "..") %tr{ :class => "tree-item", :url => tree_file_project_path(@project, @commit.id, file) } %td.tree-item-file-name = image_tag "dir.png" = link_to "..", tree_file_project_path(@project, @commit.id, file, :branch => @branch, :tag => @tag), :remote => :true - %td - %td + %td + %td - contents.select{ |i| i.is_a?(Grit::Tree)}.each do |content| = render :partial => "projects/tree_item", :locals => { :content => content } @@ -52,7 +52,7 @@ }); - if params[:path] && request.xhr? - :javascript + :javascript $(window).unbind('popstate'); $(window).bind('popstate', function() { if(location.pathname.search("tree") != -1) { diff --git a/app/views/projects/_tree_file.html.haml b/app/views/projects/_tree_file.html.haml index 41a2287a..b5b18213 100644 --- a/app/views/projects/_tree_file.html.haml +++ b/app/views/projects/_tree_file.html.haml @@ -4,7 +4,7 @@ %strong = name = link_to "raw", blob_project_path(@project, :commit_id => @commit.id, :path => params[:path] ), :class => "right", :target => "_blank" - = link_to "history", project_commits_path(@project, :path => params[:path]), :class => "right", :style => "margin-right:10px;" + = link_to "history", project_commits_path(@project, :path => params[:path], :branch => params[:branch], :tag => params[:tag] ), :class => "right", :style => "margin-right:10px;" %br/ - if file.text? .view_file_content @@ -14,6 +14,6 @@ .view_file_content_image %img{ :src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} - else - %p + %p %center No preview for this file type From 5baa5fad0a1c6e2b8790f07f62c088fd505406d9 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Mon, 24 Oct 2011 22:38:03 +0300 Subject: [PATCH 098/176] Issue #149 --- app/helpers/commits_helper.rb | 9 --------- app/views/commits/_commits.html.haml | 2 +- app/views/commits/show.html.haml | 2 +- app/views/projects/_recent_commits.html.haml | 2 +- app/views/projects/_recent_messages.html.haml | 2 +- app/views/projects/_tree_item.html.haml | 2 +- config/initializers/grit_ext.rb | 4 ++++ lib/commit_ext.rb | 9 +++++++++ 8 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 lib/commit_ext.rb diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index b79e5718..f1b54668 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -21,13 +21,4 @@ module CommitsHelper link_to "More", project_commits_path(@project, :offset => offset.to_i + limit.to_i, :limit => limit), :remote => true, :class => "lite_button vm", :style => "text-align:center; width:930px; ", :id => "more-commits-link" end - - # Cause some errors with trucate & encoding use this method - def truncate_commit_message(commit, size = 60) - message = commit.message - message.length > size ? (message[0..(size - 1)] + "...") : message - # if special characters occurs - rescue - commit.message - end end diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index 94a1bd1b..3ed70f1c 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -11,7 +11,7 @@ = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" %p %strong - = truncate_commit_message(commit) + = commit.truncated_message = link_to "Browse Code", tree_project_path(@project, :commit_id => commit.id), :class => "lite_button", :style => "float:right" = link_to truncate(commit.id.to_s, :length => 16), project_commit_path(@project, :id => commit.id), :class => "lite_button", :style => "width:120px;float:right" %span diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml index a2c9149d..0ba42618 100644 --- a/app/views/commits/show.html.haml +++ b/app/views/commits/show.html.haml @@ -1,5 +1,5 @@ %h3 - = "[ #{@commit.committer} ] #{truncate_commit_message(@commit, 80)}" + = "[ #{@commit.committer} ] #{@commit.truncated_message(40)}" -#= link_to 'Back', project_commits_path(@project), :class => "button" %table.round-borders %tr diff --git a/app/views/projects/_recent_commits.html.haml b/app/views/projects/_recent_commits.html.haml index e435ea30..36f4b636 100644 --- a/app/views/projects/_recent_commits.html.haml +++ b/app/views/projects/_recent_commits.html.haml @@ -6,7 +6,7 @@ = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" %p{:style => "margin-bottom: 3px;"} %strong - = link_to truncate_commit_message(commit, 60), project_commit_path(@project, :id => commit.id) + = link_to commit.truncated_message(60), project_commit_path(@project, :id => commit.id) %span %span.author diff --git a/app/views/projects/_recent_messages.html.haml b/app/views/projects/_recent_messages.html.haml index 1af7fe3b..36f1435b 100644 --- a/app/views/projects/_recent_messages.html.haml +++ b/app/views/projects/_recent_messages.html.haml @@ -19,7 +19,7 @@ - css_class = "dash_commit" - commit = parent - item_code = commit.author.email - - link_item_name = truncate_commit_message(commit, 50) + - link_item_name = commit.truncated_message(50) - link_to_item = project_commit_path(@project, :id => commit.id) - else - css_class = "dash_wall" diff --git a/app/views/projects/_tree_item.html.haml b/app/views/projects/_tree_item.html.haml index 4ebcfbef..538d2cc6 100644 --- a/app/views/projects/_tree_item.html.haml +++ b/app/views/projects/_tree_item.html.haml @@ -12,4 +12,4 @@ = time_ago_in_words(content_commit.committed_date) ago %td - = link_to truncate_commit_message(content_commit, 40), project_commit_path(@project, content_commit) + = link_to content_commit.truncated_message(40), project_commit_path(@project, content_commit) diff --git a/config/initializers/grit_ext.rb b/config/initializers/grit_ext.rb index 4bd71003..9231da6f 100644 --- a/config/initializers/grit_ext.rb +++ b/config/initializers/grit_ext.rb @@ -6,3 +6,7 @@ Grit::Blob.class_eval do include Utils::FileHelper include Utils::Colorize end + +Grit::Commit.class_eval do + include CommitExt +end diff --git a/lib/commit_ext.rb b/lib/commit_ext.rb new file mode 100644 index 00000000..c175fa0c --- /dev/null +++ b/lib/commit_ext.rb @@ -0,0 +1,9 @@ +module CommitExt + # Cause of encoding rails truncate raise error + # this method is temporary decision + def truncated_message(size = 80) + message.length > size ? (message[0..(size - 1)] + "...") : message + rescue + "-- invalid encoding for commit message" + end +end From afe98ae74ab13d11908e74ada1d10dccc333228b Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 25 Oct 2011 07:32:02 +0300 Subject: [PATCH 099/176] Issue #149 fixed --- app/views/commits/_commits.html.haml | 2 +- app/views/commits/show.html.haml | 4 ++-- app/views/projects/_recent_commits.html.haml | 2 +- app/views/projects/_recent_messages.html.haml | 2 +- app/views/projects/_tree_item.html.haml | 2 +- lib/commit_ext.rb | 10 ++++++---- spec/requests/team_members_spec.rb | 4 +++- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index 3ed70f1c..99823065 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -11,7 +11,7 @@ = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" %p %strong - = commit.truncated_message + = truncate(commit.safe_message, :length => 60) = link_to "Browse Code", tree_project_path(@project, :commit_id => commit.id), :class => "lite_button", :style => "float:right" = link_to truncate(commit.id.to_s, :length => 16), project_commit_path(@project, :id => commit.id), :class => "lite_button", :style => "width:120px;float:right" %span diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml index 0ba42618..3beeada8 100644 --- a/app/views/commits/show.html.haml +++ b/app/views/commits/show.html.haml @@ -1,5 +1,5 @@ %h3 - = "[ #{@commit.committer} ] #{@commit.truncated_message(40)}" + = "[ #{@commit.committer} ] #{truncate(@commit.safe_message)}" -#= link_to 'Back', project_commits_path(@project), :class => "button" %table.round-borders %tr @@ -16,7 +16,7 @@ %td= @commit.committed_date %tr %td Message - %td= @commit.message + %td= @commit.safe_message %tr %td Tree %td= link_to 'Browse Code', tree_project_path(@project, :commit_id => @commit.id) diff --git a/app/views/projects/_recent_commits.html.haml b/app/views/projects/_recent_commits.html.haml index 36f4b636..3157c356 100644 --- a/app/views/projects/_recent_commits.html.haml +++ b/app/views/projects/_recent_commits.html.haml @@ -6,7 +6,7 @@ = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" %p{:style => "margin-bottom: 3px;"} %strong - = link_to commit.truncated_message(60), project_commit_path(@project, :id => commit.id) + = link_to truncate(commit.safe_message, :length => 60), project_commit_path(@project, :id => commit.id) %span %span.author diff --git a/app/views/projects/_recent_messages.html.haml b/app/views/projects/_recent_messages.html.haml index 36f1435b..67f3449b 100644 --- a/app/views/projects/_recent_messages.html.haml +++ b/app/views/projects/_recent_messages.html.haml @@ -19,7 +19,7 @@ - css_class = "dash_commit" - commit = parent - item_code = commit.author.email - - link_item_name = commit.truncated_message(50) + - link_item_name = truncate(commit.safe_message, :length => 50) - link_to_item = project_commit_path(@project, :id => commit.id) - else - css_class = "dash_wall" diff --git a/app/views/projects/_tree_item.html.haml b/app/views/projects/_tree_item.html.haml index 538d2cc6..53c05d5a 100644 --- a/app/views/projects/_tree_item.html.haml +++ b/app/views/projects/_tree_item.html.haml @@ -12,4 +12,4 @@ = time_ago_in_words(content_commit.committed_date) ago %td - = link_to content_commit.truncated_message(40), project_commit_path(@project, content_commit) + = link_to truncate(content_commit.safe_message, :length => 40), project_commit_path(@project, content_commit) diff --git a/lib/commit_ext.rb b/lib/commit_ext.rb index c175fa0c..e09dbdaf 100644 --- a/lib/commit_ext.rb +++ b/lib/commit_ext.rb @@ -1,8 +1,10 @@ module CommitExt - # Cause of encoding rails truncate raise error - # this method is temporary decision - def truncated_message(size = 80) - message.length > size ? (message[0..(size - 1)] + "...") : message + def safe_message + message.encode("UTF-8", + :invalid => :replace, + :undef => :replace, + :universal_newline => true, + :replace => "") rescue "-- invalid encoding for commit message" end diff --git a/spec/requests/team_members_spec.rb b/spec/requests/team_members_spec.rb index ec0af321..650ed449 100644 --- a/spec/requests/team_members_spec.rb +++ b/spec/requests/team_members_spec.rb @@ -10,7 +10,9 @@ describe "TeamMembers" do describe "View profile" do it "should be available" do visit(team_project_path(@project)) - find(:xpath, "//table[@id='team-table']//a[1]").click + within "#team-table" do + click_link(@user.name) + end page.should have_content @user.skype page.should_not have_content 'Twitter' end From 9afee5ad5298dc4c89ec74c5fda44adfc91de1b2 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 25 Oct 2011 07:34:02 +0300 Subject: [PATCH 100/176] Add critical status to issues --- app/assets/stylesheets/projects.css.scss | 34 +++++++++++++++++++ app/controllers/issues_controller.rb | 2 +- app/models/issue.rb | 11 ++++++ app/views/issues/_form.html.haml | 12 ++++--- app/views/issues/_issues.html.haml | 7 +++- app/views/issues/_show.html.haml | 20 +++++++++-- .../20111025134235_add_high_label_to_issue.rb | 5 +++ db/schema.rb | 3 +- 8 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 db/migrate/20111025134235_add_high_label_to_issue.rb diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 8caa2810..3e7633a6 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -647,3 +647,37 @@ tbody tr:nth-child(2n) td, tbody tr.even td { background: none repeat scroll 0 0 #FFBBBB } } + +.tag { + @include round-borders-all(4px); + padding:2px 4px; + border:none; + + &.high { + background: #D12F19; + color:white; + } + + &.today { + background: #44aa22; + color:white; + } + + &.yours { + background: #4466cc; + color:white; + } + &.notes { + background: #2c5c66; + color:white; + } +} + +#issues-table .issue { + &.critical { + td { + //background: #D12F19; + //color:#fff; + } + } +} diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index cf8e1ebe..757ada94 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -12,7 +12,7 @@ class IssuesController < ApplicationController def index @issues = case params[:f].to_i - when 1 then @project.issues.all + when 1 then @project.issues when 2 then @project.issues.closed when 3 then @project.issues.opened.assigned(current_user) else @project.issues.opened diff --git a/app/models/issue.rb b/app/models/issue.rb index 556cdc1c..904965ac 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -18,11 +18,22 @@ class Issue < ActiveRecord::Base :presence => true, :length => { :within => 0..2000 } + scope :critical, where(:critical => true) + scope :non_critical, where(:critical => false) + scope :opened, where(:closed => false) scope :closed, where(:closed => true) scope :assigned, lambda { |u| where(:assignee_id => u.id)} acts_as_list + + def today? + Date.today == created_at.to_date + end + + def new? + today? && created_at == updated_at + end end # == Schema Information # diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml index 71acdba1..eae0ee0f 100644 --- a/app/views/issues/_form.html.haml +++ b/app/views/issues/_form.html.haml @@ -5,17 +5,21 @@ - @issue.errors.full_messages.each do |msg| %li= msg - .span-6 + .span-8 = f.label :title = f.text_field :title, :style => "width:450px" - .span-6 + .span-8 = f.label :content = f.text_area :content, :style => "width:450px; height:130px" - .span-6.append-bottom + .span-8.append-bottom = f.label :assignee_id = f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }) + .span-1 + = f.label :critical, "Critical" + %br + = f.check_box :critical - unless @issue.new_record? - .span-3.right + .span-2.right = f.label :closed %br = f.check_box :closed diff --git a/app/views/issues/_issues.html.haml b/app/views/issues/_issues.html.haml index d3e21940..42e8371a 100644 --- a/app/views/issues/_issues.html.haml +++ b/app/views/issues/_issues.html.haml @@ -1,10 +1,15 @@ %table.round-borders#issues-table %tr + - if can?(current_user, :admin_issue, @project) && !params[:f] || params[:f] == "0" + %th %th Assignee %th ID %th Title %th Closed? %th - - @issues.each do |issue| + - @issues.critical.each do |issue| + = render(:partial => 'show', :locals => {:issue => issue}) + + - @issues.non_critical.each do |issue| = render(:partial => 'show', :locals => {:issue => issue}) diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml index 30157257..fcac006e 100644 --- a/app/views/issues/_show.html.haml +++ b/app/views/issues/_show.html.haml @@ -1,10 +1,24 @@ -%tr{ :id => dom_id(issue), :class => "issue", :url => project_issue_path(@project, issue) } +%tr{ :id => dom_id(issue), :class => "issue #{issue.critical ? "critical" : ""}", :url => project_issue_path(@project, issue) } + - if can?(current_user, :admin_issue, @project) && !params[:f] || params[:f] == "0" + %td + = image_tag "move.png" , :class => [:handle, :left] %td - = image_tag "move.png" , :class => [:handle, :left] = image_tag gravatar_icon(issue.assignee.email), :class => "left", :width => 40, :style => "padding:0 5px;" = truncate issue.assignee.name, :lenght => 20 %td ##{issue.id} - %td= html_escape issue.title + %td + = html_escape issue.title + %br + - if issue.critical + %span.tag.high critical + - if issue.today? + %span.tag.today today + -#- if issue.author == current_user + -#%span.tag.yours yours + -#- if issue.notes.count > 0 + -#%span.tag.notes + -#= issue.notes.count + -#notes %td - if can? current_user, :write_issue, @project = form_for([@project, issue], :remote => true) do |f| diff --git a/db/migrate/20111025134235_add_high_label_to_issue.rb b/db/migrate/20111025134235_add_high_label_to_issue.rb new file mode 100644 index 00000000..676eaaf8 --- /dev/null +++ b/db/migrate/20111025134235_add_high_label_to_issue.rb @@ -0,0 +1,5 @@ +class AddHighLabelToIssue < ActiveRecord::Migration + def change + add_column :issues, :critical, :boolean, :default => false, :null => false + end +end diff --git a/db/schema.rb b/db/schema.rb index cc805990..21c224d4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111021101550) do +ActiveRecord::Schema.define(:version => 20111025134235) do create_table "issues", :force => true do |t| t.string "title" @@ -23,6 +23,7 @@ ActiveRecord::Schema.define(:version => 20111021101550) do t.datetime "updated_at" t.boolean "closed", :default => false, :null => false t.integer "position", :default => 0 + t.boolean "critical", :default => false, :null => false end create_table "keys", :force => true do |t| From f6a67fbad5119e3d95e33cfd4f4e4992707d5ba0 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 25 Oct 2011 21:04:31 +0300 Subject: [PATCH 101/176] Issue #87 --- app/views/commits/_text_file.html.haml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml index b20aa8af..67033ade 100644 --- a/app/views/commits/_text_file.html.haml +++ b/app/views/commits/_text_file.html.haml @@ -1,8 +1,14 @@ +- line_old = 0 +- line_new = 0 - lines_arr = diff.diff.lines.to_a -- line_old = lines_arr[2].match(/-(\d)/)[0].to_i.abs rescue 0 -- line_new = lines_arr[2].match(/\+(\d)/)[0].to_i.abs rescue 0 -- lines = lines_arr[3..-1].join -- lines.each_line do |line| +- lines_arr.each do |line| + - next if line.match(/^--- a/) + - next if line.match(/^\+\+\+ b/) + - if line.match(/^@@ -/) + - line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0 + - line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0 + - next + = diff_line(line, line_new, line_old) - if line[0] == "+" - line_new += 1 From 92f6de03703cb64fb5758c629a83522287af2d19 Mon Sep 17 00:00:00 2001 From: Adam Leonard Date: Tue, 25 Oct 2011 20:15:11 -0400 Subject: [PATCH 102/176] If terms are removed show all results for current status --- app/controllers/issues_controller.rb | 13 ++++++++-- app/views/issues/index.html.haml | 33 +++++++++++++++---------- spec/requests/issues_spec.rb | 37 +++++++++++++++++++++++----- 3 files changed, 62 insertions(+), 21 deletions(-) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 71338a61..93cf19b6 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -79,8 +79,17 @@ class IssuesController < ApplicationController end def search - @project = Project.find(params['project']) - @issues = @project.issues.where("title LIKE ? OR content LIKE ?", "%#{params['terms']}%", "%#{params['terms']}%") + terms = params['terms'] + + @project = Project.find(params['project']) + @issues = case params[:status].to_i + when 1 then @project.issues + when 2 then @project.issues.closed + when 3 then @project.issues.opened.assigned(current_user) + else @project.issues.opened + end + + @issues = @issues.where("title LIKE ? OR content LIKE ?", "%#{terms}%", "%#{terms}%") unless terms.blank? render :partial => 'issues' end diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml index 53c4fe66..7e4694ef 100644 --- a/app/views/issues/index.html.haml +++ b/app/views/issues/index.html.haml @@ -2,37 +2,44 @@ - if can? current_user, :write_issue, @project .left = form_tag search_project_issues_path(@project), :method => :get, :remote => true do + = hidden_field_tag :project_id, @project.id, { :id => 'project_id' } = search_field_tag :issue_search, nil, { :placeholder => 'Search', :class => 'issue_search' } = link_to 'New Issue', new_project_issue_path(@project), :remote => true, :class => "lbutton vm" .right = form_tag project_issues_path(@project), :method => :get do .span-2 - = radio_button_tag :f, 0, (params[:f] || "0") == "0", :onclick => "this.form.submit()", :id => "open_issues" + = radio_button_tag :f, 0, (params[:f] || "0") == "0", :onclick => "this.form.submit()", :id => "open_issues", :class => "status" = label_tag "open_issues","Open" .span-2 - = radio_button_tag :f, 2, params[:f] == "2", :onclick => "this.form.submit()", :id => "closed_issues" + = radio_button_tag :f, 2, params[:f] == "2", :onclick => "this.form.submit()", :id => "closed_issues", :class => "status" = label_tag "closed_issues","Closed" .span-2 - = radio_button_tag :f, 3, params[:f] == "3", :onclick => "this.form.submit()", :id => "my_issues" + = radio_button_tag :f, 3, params[:f] == "3", :onclick => "this.form.submit()", :id => "my_issues", :class => "status" = label_tag "my_issues","To Me" - .span-2 - = radio_button_tag :f, 1, params[:f] == "1", :onclick => "this.form.submit()", :id => "all_issues" + = radio_button_tag :f, 1, params[:f] == "1", :onclick => "this.form.submit()", :id => "all_issues", :class => "status" = label_tag "all_issues","All" #issues-table-holder= render "issues" %br :javascript - $('.issue_search').keyup(function() { - var terms = $(this).val(); - var project_id = 1; + var href = $('.issue_search').parent().attr('action'); + var last_terms = ''; - if (terms.length >= 2) { - $.get($(this).parent().attr('action'), { 'terms': terms, project: project_id }, function(response) { - $('#issues-table').html(response); - setSortable(); - }); + $('.issue_search').keyup(function() { + var terms = $(this).val(); + var project_id = $('#project_id').val(); + var status = $('.status:checked').val(); + if (terms != last_terms) { + last_terms = terms; + + if (terms.length >= 2 || terms.length == 0) { + $.get(href, { 'status': status, 'terms': terms, project: project_id }, function(response) { + $('#issues-table').html(response); + setSortable(); + }); + } } }); diff --git a/spec/requests/issues_spec.rb b/spec/requests/issues_spec.rb index d3582d16..b7f4d411 100644 --- a/spec/requests/issues_spec.rb +++ b/spec/requests/issues_spec.rb @@ -149,21 +149,46 @@ describe "Issues" do before do ['foobar', 'foobar2', 'gitlab'].each do |title| @issue = Factory :issue, - :author => @user, + :author => @user, :assignee => @user, - :project => project, - :title => title + :project => project, + :title => title @issue.save end end - it "should search and return the correct results" do + it "should be able to search on different statuses" do + @issue = Issue.first + @issue.closed = true + @issue.save + visit project_issues_path(project) - fill_in "issue_search", :with => "foobar" + choose 'closed_issues' + fill_in 'issue_search', :with => 'foobar' + + page.should have_content 'foobar' + page.should_not have_content 'foobar2' + page.should_not have_content 'gitlab' + end + + it "should search for term and return the correct results" do + visit project_issues_path(project) + fill_in 'issue_search', :with => 'foobar' + page.should have_content 'foobar' page.should have_content 'foobar2' page.should_not have_content 'gitlab' end - end + it "should return all results if term has been cleared" do + visit project_issues_path(project) + fill_in "issue_search", :with => "foobar" + # Because fill_in, :with => "" triggers nothing we need to trigger a keyup event + page.execute_script("$('.issue_search').val('').keyup();"); + + page.should have_content 'foobar' + page.should have_content 'foobar2' + page.should have_content 'gitlab' + end + end end From 7d773ecb40c9309d888c5e09814f5fbf7df67a11 Mon Sep 17 00:00:00 2001 From: Adam Leonard Date: Tue, 25 Oct 2011 20:15:59 -0400 Subject: [PATCH 103/176] Remove mysql2 gem --- Gemfile | 1 - Gemfile.lock | 2 -- 2 files changed, 3 deletions(-) diff --git a/Gemfile b/Gemfile index ad15fc83..77a00659 100644 --- a/Gemfile +++ b/Gemfile @@ -20,7 +20,6 @@ gem "kaminari" gem "thin" gem "git" gem "acts_as_list" -gem "mysql2" group :assets do gem 'sass-rails', " ~> 3.1.0" diff --git a/Gemfile.lock b/Gemfile.lock index a881b05e..5ba34459 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -128,7 +128,6 @@ GEM treetop (~> 1.4.8) mime-types (1.16) multi_json (1.0.3) - mysql2 (0.3.7) nokogiri (1.5.0) orm_adapter (0.0.5) polyglot (0.3.2) @@ -259,7 +258,6 @@ DEPENDENCIES jquery-rails kaminari launchy - mysql2 pygments.rb (= 0.2.3) rails (= 3.1.0) rails-footnotes (>= 3.7.5.rc4) From fb01f45890da1883d622b4550af2bf997c029764 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Wed, 26 Oct 2011 07:34:02 +0300 Subject: [PATCH 104/176] issue search styleup --- app/assets/stylesheets/projects.css.scss | 17 ++++++++++ app/views/issues/index.html.haml | 43 ++++++++++++------------ config/database.yml | 19 ++++++----- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 3e7633a6..2e97bdde 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -681,3 +681,20 @@ tbody tr:nth-child(2n) td, tbody tr.even td { } } } + +.top_panel_issues{ + #issue_search_form { + margin:5px 0; + input { + border:1px solid #D3D3D3; + padding: 3px; + height: 20px; + width: 300px; + + &:focus { + border-color:#c2e1ef; + } + } + } +} + diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml index 7e4694ef..73d446be 100644 --- a/app/views/issues/index.html.haml +++ b/app/views/issues/index.html.haml @@ -1,25 +1,26 @@ %div - - if can? current_user, :write_issue, @project - .left - = form_tag search_project_issues_path(@project), :method => :get, :remote => true do - = hidden_field_tag :project_id, @project.id, { :id => 'project_id' } - = search_field_tag :issue_search, nil, { :placeholder => 'Search', :class => 'issue_search' } - = link_to 'New Issue', new_project_issue_path(@project), :remote => true, :class => "lbutton vm" - - .right - = form_tag project_issues_path(@project), :method => :get do - .span-2 - = radio_button_tag :f, 0, (params[:f] || "0") == "0", :onclick => "this.form.submit()", :id => "open_issues", :class => "status" - = label_tag "open_issues","Open" - .span-2 - = radio_button_tag :f, 2, params[:f] == "2", :onclick => "this.form.submit()", :id => "closed_issues", :class => "status" - = label_tag "closed_issues","Closed" - .span-2 - = radio_button_tag :f, 3, params[:f] == "3", :onclick => "this.form.submit()", :id => "my_issues", :class => "status" - = label_tag "my_issues","To Me" - .span-2 - = radio_button_tag :f, 1, params[:f] == "1", :onclick => "this.form.submit()", :id => "all_issues", :class => "status" - = label_tag "all_issues","All" + .top_panel_issues + - if can? current_user, :write_issue, @project + %div{:class => "left", :style => "margin-right: 10px;" } + = link_to 'New Issue', new_project_issue_path(@project), :remote => true, :class => "lbutton vm" + = form_tag search_project_issues_path(@project), :method => :get, :remote => true, :class => :left, :id => "issue_search_form" do + = hidden_field_tag :project_id, @project.id, { :id => 'project_id' } + = search_field_tag :issue_search, nil, { :placeholder => 'Search', :class => 'issue_search' } + + .right + = form_tag project_issues_path(@project), :method => :get do + .span-2 + = radio_button_tag :f, 0, (params[:f] || "0") == "0", :onclick => "this.form.submit()", :id => "open_issues", :class => "status" + = label_tag "open_issues","Open" + .span-2 + = radio_button_tag :f, 2, params[:f] == "2", :onclick => "this.form.submit()", :id => "closed_issues", :class => "status" + = label_tag "closed_issues","Closed" + .span-2 + = radio_button_tag :f, 3, params[:f] == "3", :onclick => "this.form.submit()", :id => "my_issues", :class => "status" + = label_tag "my_issues","To Me" + .span-2 + = radio_button_tag :f, 1, params[:f] == "1", :onclick => "this.form.submit()", :id => "all_issues", :class => "status" + = label_tag "all_issues","All" #issues-table-holder= render "issues" %br diff --git a/config/database.yml b/config/database.yml index 59e1f12c..51a4dd45 100644 --- a/config/database.yml +++ b/config/database.yml @@ -4,9 +4,8 @@ # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' development: - adapter: mysql2 - database: gitlab_development - username: root + adapter: sqlite3 + database: db/development.sqlite3 pool: 5 timeout: 5000 @@ -14,11 +13,13 @@ development: # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - adapter: mysql2 - database: gitlab_development - username: root + adapter: sqlite3 + database: db/test.sqlite3 + pool: 5 + timeout: 5000 production: - adatper: mysql2 - database: gitlab_test - username: root + adapter: sqlite3 + database: db/production.sqlite3 + pool: 5 + timeout: 5000 From 1beb84161c80eec8c5df2ca3888409143f25a8e0 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Wed, 26 Oct 2011 07:44:02 +0300 Subject: [PATCH 105/176] search field style --- app/assets/stylesheets/projects.css.scss | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 2e97bdde..c1700537 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -688,8 +688,11 @@ tbody tr:nth-child(2n) td, tbody tr.even td { input { border:1px solid #D3D3D3; padding: 3px; - height: 20px; + height: 28px; width: 300px; + -webkit-appearance:none; + box-sizing: border-box; + -moz-box-sizing: border-box; &:focus { border-color:#c2e1ef; From d62200cad430565bd9f80befaf329297120330b5 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Wed, 26 Oct 2011 18:46:25 +0500 Subject: [PATCH 106/176] clean-up code * Remove trailing whitespace * Converts hard-tabs into two-space soft-tabs * Remove consecutive blank lines --- .../jquery-ui-1.8.16.custom.min.js | 100 +- .../javascripts/jquery.ui.selectmenu.js | 1655 ++++++++--------- app/assets/javascripts/projects.js | 2 +- app/assets/stylesheets/application.css | 2 +- app/assets/stylesheets/highlight.css.scss | 16 +- .../stylesheets/jquery.ui.selectmenu.css | 2 +- app/assets/stylesheets/projects.css.scss | 191 +- app/controllers/admin/mailer_controller.rb | 6 +- app/controllers/admin/users_controller.rb | 6 +- app/controllers/application_controller.rb | 6 +- app/controllers/issues_controller.rb | 9 +- app/controllers/keys_controller.rb | 2 +- app/controllers/notes_controller.rb | 11 +- app/controllers/profile_controller.rb | 2 +- app/controllers/projects_controller.rb | 24 +- app/controllers/snippets_controller.rb | 6 +- app/controllers/team_members_controller.rb | 8 +- app/helpers/application_helper.rb | 16 +- app/helpers/commits_helper.rb | 6 +- app/helpers/projects_helper.rb | 2 +- app/models/ability.rb | 10 +- app/models/issue.rb | 4 +- app/models/key.rb | 4 +- app/models/note.rb | 10 +- app/models/project.rb | 20 +- app/models/snippet.rb | 5 +- app/models/user.rb | 2 +- app/views/admin/mailer/preview.html.haml | 15 +- app/views/admin/projects/show.html.haml | 8 +- app/views/admin/team_members/index.html.haml | 4 +- app/views/admin/team_members/show.html.haml | 1 - app/views/admin/users/_form.html.haml | 2 +- app/views/admin/users/new.html.haml | 1 - app/views/admin/users/show.html.haml | 9 +- app/views/commits/_diff.html.haml | 4 +- app/views/commits/_index.html.haml | 2 +- app/views/commits/_text_file.html.haml | 4 +- app/views/commits/show.js.haml | 2 +- app/views/devise/confirmations/new.html.erb | 2 +- app/views/devise/passwords/edit.html.erb | 2 +- app/views/devise/shared/_links.erb | 2 +- app/views/devise/unlocks/new.html.erb | 2 +- app/views/issues/_issues.html.haml | 2 +- app/views/issues/_show.html.haml | 4 +- app/views/issues/index.html.haml | 8 +- app/views/issues/show.html.haml | 15 +- app/views/issues/show.js.haml | 2 +- app/views/issues/update.js.haml | 2 +- app/views/keys/index.html.haml | 4 +- app/views/layouts/_flash.html.haml | 6 +- app/views/layouts/_head_panel.html.erb | 1 - app/views/notes/_form.html.haml | 2 +- app/views/notes/_notes.html.haml | 11 +- app/views/notes/create.js.haml | 2 +- app/views/notify/new_issue_email.html.haml | 4 +- app/views/notify/new_user_email.html.haml | 2 +- app/views/notify/note_issue_email.html.haml | 6 +- app/views/notify/note_wall_email.html.haml | 2 +- app/views/projects/_form.html.haml | 10 +- app/views/projects/_list.html.haml | 2 +- .../projects/_projects_top_menu.html.haml | 2 +- app/views/projects/_recent_commits.html.haml | 4 +- app/views/projects/_team.html.haml | 4 +- app/views/projects/empty.html.erb | 2 +- app/views/projects/index.html.haml | 2 +- app/views/projects/tree.js.haml | 2 +- app/views/projects/wall.html.haml | 2 +- app/views/projects/wall.js.haml | 2 +- app/views/snippets/_form.html.haml | 2 +- app/views/snippets/index.html.haml | 4 +- app/views/team_members/_show.html.haml | 4 +- app/views/team_members/show.html.haml | 1 - config/environments/production.rb | 1 - config/initializers/grit_ext.rb | 2 +- config/routes.rb | 10 +- .../20110913200833_devise_create_users.rb | 1 - lib/color.rb | 2 +- lib/commit_ext.rb | 8 +- lib/file_size_validator.rb | 4 +- lib/utils.rb | 4 +- public/index.html.example | 5 - spec/factory.rb | 6 +- spec/models/issue_spec.rb | 2 +- spec/models/key_spec.rb | 2 +- spec/models/note_spec.rb | 32 +- spec/models/project_security_spec.rb | 28 +- spec/models/project_spec.rb | 34 +- spec/models/user_spec.rb | 2 +- spec/models/users_project_spec.rb | 2 +- spec/monkeypatch.rb | 6 +- spec/requests/admin/admin_projects_spec.rb | 36 +- spec/requests/admin/admin_users_spec.rb | 34 +- spec/requests/admin/security_spec.rb | 8 +- spec/requests/commits_notes_spec.rb | 6 +- spec/requests/commits_spec.rb | 14 +- spec/requests/issues_notes_spec.rb | 6 +- spec/requests/issues_spec.rb | 44 +- spec/requests/keys_spec.rb | 18 +- spec/requests/profile_spec.rb | 27 +- spec/requests/projects_security_spec.rb | 34 +- spec/requests/projects_spec.rb | 40 +- .../requests/projects_tree_perfomance_spec.rb | 8 +- spec/requests/projects_tree_spec.rb | 14 +- spec/requests/projects_wall_spec.rb | 8 +- spec/requests/snippets_spec.rb | 30 +- spec/requests/team_members_spec.rb | 24 +- spec/requests/top_panel_spec.rb | 8 +- spec/requests/user_security_spec.rb | 10 +- spec/spec_helper.rb | 1 - spec/support/login.rb | 8 +- spec/support/matchers.rb | 6 +- spec/support/shared_examples.rb | 7 +- 112 files changed, 1408 insertions(+), 1437 deletions(-) diff --git a/app/assets/javascripts/jquery-ui-1.8.16.custom.min.js b/app/assets/javascripts/jquery-ui-1.8.16.custom.min.js index 14c9064f..d92b7a34 100644 --- a/app/assets/javascripts/jquery-ui-1.8.16.custom.min.js +++ b/app/assets/javascripts/jquery-ui-1.8.16.custom.min.js @@ -41,7 +41,7 @@ c);return this},enable:function(){return this._setOption("disabled",false)},disa * http://docs.jquery.com/UI/Mouse * * Depends: - * jquery.ui.widget.js + * jquery.ui.widget.js */ (function(b){var d=false;b(document).mouseup(function(){d=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(c){return a._mouseDown(c)}).bind("click."+this.widgetName,function(c){if(true===b.data(c.target,a.widgetName+".preventClickEvent")){b.removeData(c.target,a.widgetName+".preventClickEvent");c.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+ this.widgetName)},_mouseDown:function(a){if(!d){this._mouseStarted&&this._mouseUp(a);this._mouseDownEvent=a;var c=this,f=a.which==1,g=typeof this.options.cancel=="string"&&a.target.nodeName?b(a.target).closest(this.options.cancel).length:false;if(!f||g||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){c.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted= @@ -74,9 +74,9 @@ g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"lef * http://docs.jquery.com/UI/Draggables * * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js */ (function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== "original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= @@ -124,10 +124,10 @@ p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(k-n)<=e;q=Math.abs(m-o)<=e;r=Math. * http://docs.jquery.com/UI/Droppables * * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.mouse.js - * jquery.ui.draggable.js + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.mouse.js + * jquery.ui.draggable.js */ (function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this); a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b
      ').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), @@ -200,9 +200,9 @@ d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f * http://docs.jquery.com/UI/Selectables * * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js */ (function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"), selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("
      ")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX, @@ -222,9 +222,9 @@ e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass(" * http://docs.jquery.com/UI/Sortables * * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js */ (function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){var a=this.options;this.containerCache={};this.element.addClass("ui-sortable"); this.refresh();this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a=== @@ -282,8 +282,8 @@ _uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placehold * http://docs.jquery.com/UI/Accordion * * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js + * jquery.ui.core.js + * jquery.ui.widget.js */ (function(c){c.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"); a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); @@ -312,9 +312,9 @@ paddingTop:"hide",paddingBottom:"hide"},a);else a.toShow.animate({height:"show", * http://docs.jquery.com/UI/Autocomplete * * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.position.js + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js */ (function(d){var e=0;d.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var a=this,b=this.element[0].ownerDocument,g;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.propAttr("readOnly"))){g= false;var f=d.ui.keyCode;switch(c.keyCode){case f.PAGE_UP:a._move("previousPage",c);break;case f.PAGE_DOWN:a._move("nextPage",c);break;case f.UP:a._move("previous",c);c.preventDefault();break;case f.DOWN:a._move("next",c);c.preventDefault();break;case f.ENTER:case f.NUMPAD_ENTER:if(a.menu.active){g=true;c.preventDefault()}case f.TAB:if(!a.menu.active)return;a.menu.select(c);break;case f.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!= @@ -344,8 +344,8 @@ this.first()?":last":":first"))},hasScroll:function(){return this.element.height * http://docs.jquery.com/UI/Button * * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js + * jquery.ui.core.js + * jquery.ui.widget.js */ (function(b){var h,i,j,g,l=function(){var a=b(this).find(":ui-button");setTimeout(function(){a.button("refresh")},1)},k=function(a){var c=a.name,e=a.form,f=b([]);if(c)f=e?b(e).find("[name='"+c+"']"):b("[name='"+c+"']",a.ownerDocument).filter(function(){return!this.form});return f};b.widget("ui.button",{options:{disabled:null,text:true,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",l);if(typeof this.options.disabled!== "boolean")this.options.disabled=this.element.propAttr("disabled");this._determineButtonType();this.hasTitle=!!this.buttonElement.attr("title");var a=this,c=this.options,e=this.type==="checkbox"||this.type==="radio",f="ui-state-hover"+(!e?" ui-state-active":"");if(c.label===null)c.label=this.buttonElement.html();if(this.element.is(":disabled"))c.disabled=true;this.buttonElement.addClass("ui-button ui-widget ui-state-default ui-corner-all").attr("role","button").bind("mouseenter.button",function(){if(!c.disabled){b(this).addClass("ui-state-hover"); @@ -371,13 +371,13 @@ b.Widget.prototype.destroy.call(this)}})})(jQuery); * http://docs.jquery.com/UI/Dialog * * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js + * jquery.ui.core.js + * jquery.ui.widget.js * jquery.ui.button.js - * jquery.ui.draggable.js - * jquery.ui.mouse.js - * jquery.ui.position.js - * jquery.ui.resizable.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js */ (function(c,l){var m={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},n={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true},o=c.attrFn||{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true,click:true};c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false, position:{my:"center",at:"center",collision:"fit",using:function(a){var b=c(this).css(a).offset().top;b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
      ")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ @@ -411,9 +411,9 @@ c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.b * http://docs.jquery.com/UI/Slider * * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js */ (function(d){d.widget("ui.slider",d.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var a=this,b=this.options,c=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f=b.values&&b.values.length||1,e=[];this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+ this.orientation+" ui-widget ui-widget-content ui-corner-all"+(b.disabled?" ui-slider-disabled ui-disabled":""));this.range=d([]);if(b.range){if(b.range===true){if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}this.range=d("
      ").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(b.range==="min"||b.range==="max"?" ui-slider-range-"+b.range:""))}for(var j=c.length;j"); @@ -444,8 +444,8 @@ b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[f?"animate": * http://docs.jquery.com/UI/Tabs * * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js + * jquery.ui.core.js + * jquery.ui.widget.js */ (function(d,p){function u(){return++v}function w(){return++x}var v=0,x=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"
      ",remove:null,select:null,show:null,spinner:"Loading…",tabTemplate:"
    • #{label}
    • "},_create:function(){this._tabify(true)},_setOption:function(b,e){if(b=="selected")this.options.collapsible&& e==this.options.selected||this.select(e);else{this.options[b]=e;this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+u()},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+w());return d.cookie.apply(null,[b].concat(d.makeArray(arguments)))},_ui:function(b,e){return{tab:b,panel:e,index:this.anchors.index(b)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b= @@ -479,7 +479,7 @@ a.rotate(null)}:function(){t=c.selected;h()});if(b){this.element.bind("tabsshow" * http://docs.jquery.com/UI/Datepicker * * Depends: - * jquery.ui.core.js + * jquery.ui.core.js */ (function(d,C){function M(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass= "ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su", @@ -609,7 +609,7 @@ a*2-e,0,d,e)*0.5+d*0.5+b}})}(jQuery); * http://docs.jquery.com/UI/Effects/Blind * * Depends: - * jquery.effects.core.js + * jquery.effects.core.js */ (function(b){b.effects.blind=function(c){return this.queue(function(){var a=b(this),g=["position","top","bottom","left","right"],f=b.effects.setMode(a,c.options.mode||"hide"),d=c.options.direction||"vertical";b.effects.save(a,g);a.show();var e=b.effects.createWrapper(a).css({overflow:"hidden"}),h=d=="vertical"?"height":"width";d=d=="vertical"?e.height():e.width();f=="show"&&e.css(h,0);var i={};i[h]=f=="show"?d:0;e.animate(i,c.duration,c.options.easing,function(){f=="hide"&&a.hide();b.effects.restore(a, g);b.effects.removeWrapper(a);c.callback&&c.callback.apply(a[0],arguments);a.dequeue()})})}})(jQuery); @@ -623,7 +623,7 @@ g);b.effects.removeWrapper(a);c.callback&&c.callback.apply(a[0],arguments);a.deq * http://docs.jquery.com/UI/Effects/Bounce * * Depends: - * jquery.effects.core.js + * jquery.effects.core.js */ (function(e){e.effects.bounce=function(b){return this.queue(function(){var a=e(this),l=["position","top","bottom","left","right"],h=e.effects.setMode(a,b.options.mode||"effect"),d=b.options.direction||"up",c=b.options.distance||20,m=b.options.times||5,i=b.duration||250;/show|hide/.test(h)&&l.push("opacity");e.effects.save(a,l);a.show();e.effects.createWrapper(a);var f=d=="up"||d=="down"?"top":"left";d=d=="up"||d=="left"?"pos":"neg";c=b.options.distance||(f=="top"?a.outerHeight({margin:true})/3:a.outerWidth({margin:true})/ 3);if(h=="show")a.css("opacity",0).css(f,d=="pos"?-c:c);if(h=="hide")c/=m*2;h!="hide"&&m--;if(h=="show"){var g={opacity:1};g[f]=(d=="pos"?"+=":"-=")+c;a.animate(g,i/2,b.options.easing);c/=2;m--}for(g=0;g
      ").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ @@ -681,7 +681,7 @@ e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.m * http://docs.jquery.com/UI/Effects/Fade * * Depends: - * jquery.effects.core.js + * jquery.effects.core.js */ (function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); ;/* @@ -694,7 +694,7 @@ e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.m * http://docs.jquery.com/UI/Effects/Fold * * Depends: - * jquery.effects.core.js + * jquery.effects.core.js */ (function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","bottom","left","right"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1], 10)/100*f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); @@ -708,7 +708,7 @@ e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.m * http://docs.jquery.com/UI/Effects/Highlight * * Depends: - * jquery.effects.core.js + * jquery.effects.core.js */ (function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); @@ -722,7 +722,7 @@ this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments * http://docs.jquery.com/UI/Effects/Pulsate * * Depends: - * jquery.effects.core.js + * jquery.effects.core.js */ (function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c
      ').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); b.dequeue()})})}})(jQuery); -; \ No newline at end of file +; diff --git a/app/assets/javascripts/jquery.ui.selectmenu.js b/app/assets/javascripts/jquery.ui.selectmenu.js index d61d75f9..957fe4d8 100644 --- a/app/assets/javascripts/jquery.ui.selectmenu.js +++ b/app/assets/javascripts/jquery.ui.selectmenu.js @@ -12,834 +12,833 @@ (function($) { $.widget("ui.selectmenu", { - getter: "value", - version: "1.8", - eventPrefix: "selectmenu", - options: { - transferClasses: true, - typeAhead: "sequential", - style: 'dropdown', - positionOptions: { - my: "left top", - at: "left bottom", - offset: null - }, - width: null, - menuWidth: null, - handleWidth: 26, - maxHeight: null, - icons: null, - format: null, - bgImage: function() {}, - wrapperElement: "
      " - }, - - _create: function() { - var self = this, o = this.options; - - // set a default id value, generate a new random one if not set by developer - var selectmenuId = this.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 ); - - // quick array of button and menu id's - this.ids = [ selectmenuId + '-button', selectmenuId + '-menu' ]; - - // define safe mouseup for future toggling - this._safemouseup = true; - - // create menu button wrapper - this.newelement = $( '', { - 'class': this.widgetBaseClass + ' ui-widget ui-state-default ui-corner-all', - 'id' : this.ids[ 0 ], - 'role': 'button', - 'href': '#nogo', - 'tabindex': this.element.attr( 'disabled' ) ? 1 : 0, - 'aria-haspopup': true, - 'aria-owns': this.ids[ 1 ] - }); - this.newelementWrap = $( o.wrapperElement ) - .append( this.newelement ) - .insertAfter( this.element ); - - // transfer tabindex - var tabindex = this.element.attr( 'tabindex' ); - if ( tabindex ) { - this.newelement.attr( 'tabindex', tabindex ); - } - - // save reference to select in data for ease in calling methods - this.newelement.data( 'selectelement', this.element ); - - // menu icon - this.selectmenuIcon = $( '' ) - .prependTo( this.newelement ); - - // append status span to button - this.newelement.prepend( '' ); - - // make associated form label trigger focus - $( 'label[for="' + selectmenuId + '"]' ) - .attr( 'for', this.ids[0] ) - .bind( 'click.selectmenu', function() { - self.newelement[0].focus(); - return false; - }); - - // click toggle for menu visibility - this.newelement - .bind('mousedown.selectmenu', function(event) { - self._toggle(event, true); - // make sure a click won't open/close instantly - if (o.style == "popup") { - self._safemouseup = false; - setTimeout(function() { self._safemouseup = true; }, 300); - } - return false; - }) - .bind('click.selectmenu', function() { - return false; - }) - .bind("keydown.selectmenu", function(event) { - var ret = false; - switch (event.keyCode) { - case $.ui.keyCode.ENTER: - ret = true; - break; - case $.ui.keyCode.SPACE: - self._toggle(event); - break; - case $.ui.keyCode.UP: - if (event.altKey) { - self.open(event); - } else { - self._moveSelection(-1); - } - break; - case $.ui.keyCode.DOWN: - if (event.altKey) { - self.open(event); - } else { - self._moveSelection(1); - } - break; - case $.ui.keyCode.LEFT: - self._moveSelection(-1); - break; - case $.ui.keyCode.RIGHT: - self._moveSelection(1); - break; - case $.ui.keyCode.TAB: - ret = true; - break; - default: - ret = true; - } - return ret; - }) - .bind('keypress.selectmenu', function(event) { - self._typeAhead(event.which, 'mouseup'); - return true; - }) - .bind('mouseover.selectmenu focus.selectmenu', function() { - if (!o.disabled) { - $(this).addClass(self.widgetBaseClass + '-focus ui-state-hover'); - } - }) - .bind('mouseout.selectmenu blur.selectmenu', function() { - if (!o.disabled) { - $(this).removeClass(self.widgetBaseClass + '-focus ui-state-hover'); - } - }); - - // document click closes menu - $(document).bind("mousedown.selectmenu", function(event) { - self.close(event); - }); - - // change event on original selectmenu - this.element - .bind("click.selectmenu", function() { - self._refreshValue(); - }) - // FIXME: newelement can be null under unclear circumstances in IE8 - // TODO not sure if this is still a problem (fnagel 20.03.11) - .bind("focus.selectmenu", function() { - if (self.newelement) { - self.newelement[0].focus(); - } - }); - - // set width when not set via options - if (!o.width) { - o.width = this.element.outerWidth(); - } - // set menu button width - this.newelement.width(o.width); - - // hide original selectmenu element - this.element.hide(); - - // create menu portion, append to body - this.list = $( '
        ', { - 'class': 'ui-widget ui-widget-content', - 'aria-hidden': true, - 'role': 'listbox', - 'aria-labelledby': this.ids[0], - 'id': this.ids[1] - }); - this.listWrap = $( o.wrapperElement ) - .addClass( self.widgetBaseClass + '-menu' ) - .append( this.list ) - .appendTo( 'body' ); - - // transfer menu click to menu button - this.list - .bind("keydown.selectmenu", function(event) { - var ret = false; - switch (event.keyCode) { - case $.ui.keyCode.UP: - if (event.altKey) { - self.close(event, true); - } else { - self._moveFocus(-1); - } - break; - case $.ui.keyCode.DOWN: - if (event.altKey) { - self.close(event, true); - } else { - self._moveFocus(1); - } - break; - case $.ui.keyCode.LEFT: - self._moveFocus(-1); - break; - case $.ui.keyCode.RIGHT: - self._moveFocus(1); - break; - case $.ui.keyCode.HOME: - self._moveFocus(':first'); - break; - case $.ui.keyCode.PAGE_UP: - self._scrollPage('up'); - break; - case $.ui.keyCode.PAGE_DOWN: - self._scrollPage('down'); - break; - case $.ui.keyCode.END: - self._moveFocus(':last'); - break; - case $.ui.keyCode.ENTER: - case $.ui.keyCode.SPACE: - self.close(event, true); - $(event.target).parents('li:eq(0)').trigger('mouseup'); - break; - case $.ui.keyCode.TAB: - ret = true; - self.close(event, true); - $(event.target).parents('li:eq(0)').trigger('mouseup'); - break; - case $.ui.keyCode.ESCAPE: - self.close(event, true); - break; - default: - ret = true; - } - return ret; - }) - .bind('keypress.selectmenu', function(event) { - self._typeAhead(event.which, 'focus'); - return true; - }) - // this allows for using the scrollbar in an overflowed list - .bind( 'mousedown.selectmenu mouseup.selectmenu', function() { return false; }); - - // needed when window is resized - // TODO seems to be useless, but causes errors (fnagel 01.08.11) - // see: https://github.com/fnagel/jquery-ui/issues/147 - // $(window).bind( "resize.selectmenu", $.proxy( self._refreshPosition, this ) ); - }, - - _init: function() { - var self = this, o = this.options; - - // serialize selectmenu element options - var selectOptionData = []; - this.element - .find('option') - .each(function() { - var opt = $(this); - selectOptionData.push({ - value: opt.attr('value'), - text: self._formatText(opt.text()), - selected: opt.attr('selected'), - disabled: opt.attr('disabled'), - classes: opt.attr('class'), - typeahead: opt.attr('typeahead'), - parentOptGroup: opt.parent('optgroup'), - bgImage: o.bgImage.call(opt) - }); - }); - - // active state class is only used in popup style - var activeClass = (self.options.style == "popup") ? " ui-state-active" : ""; - - // empty list so we can refresh the selectmenu via selectmenu() - this.list.html(""); - - // write li's - if (selectOptionData.length) { - for (var i = 0; i < selectOptionData.length; i++) { - var thisLiAttr = { role : 'presentation' }; - if ( selectOptionData[ i ].disabled ) { - thisLiAttr[ 'class' ] = this.namespace + '-state-disabled'; - } - var thisAAttr = { - html: selectOptionData[i].text, - href : '#nogo', - tabindex : -1, - role : 'option', - 'aria-selected' : false - }; - if ( selectOptionData[ i ].disabled ) { - thisAAttr[ 'aria-disabled' ] = selectOptionData[ i ].disabled; - } - if ( selectOptionData[ i ].typeahead ) { - thisAAttr[ 'typeahead' ] = selectOptionData[ i ].typeahead; - } - var thisA = $('', thisAAttr); - var thisLi = $('
      • ', thisLiAttr) - .append(thisA) - .data('index', i) - .addClass(selectOptionData[i].classes) - .data('optionClasses', selectOptionData[i].classes || '') - .bind("mouseup.selectmenu", function(event) { - if (self._safemouseup && !self._disabled(event.currentTarget) && !self._disabled($( event.currentTarget ).parents( "ul>li." + self.widgetBaseClass + "-group " )) ) { - var changed = $(this).data('index') != self._selectedIndex(); - self.index($(this).data('index')); - self.select(event); - if (changed) { - self.change(event); - } - self.close(event, true); - } - return false; - }) - .bind("click.selectmenu", function() { - return false; - }) - .bind('mouseover.selectmenu focus.selectmenu', function(e) { - // no hover if diabled - if (!$(e.currentTarget).hasClass(self.namespace + '-state-disabled') && !$(e.currentTarget).parent("ul").parent("li").hasClass(self.namespace + '-state-disabled')) { - self._selectedOptionLi().addClass(activeClass); - self._focusedOptionLi().removeClass(self.widgetBaseClass + '-item-focus ui-state-hover'); - $(this).removeClass('ui-state-active').addClass(self.widgetBaseClass + '-item-focus ui-state-hover'); - } - }) - .bind('mouseout.selectmenu blur.selectmenu', function() { - if ($(this).is(self._selectedOptionLi().selector)) { - $(this).addClass(activeClass); - } - $(this).removeClass(self.widgetBaseClass + '-item-focus ui-state-hover'); - }); - - // optgroup or not... - if ( selectOptionData[i].parentOptGroup.length ) { - var optGroupName = self.widgetBaseClass + '-group-' + this.element.find( 'optgroup' ).index( selectOptionData[i].parentOptGroup ); - if (this.list.find( 'li.' + optGroupName ).length ) { - this.list.find( 'li.' + optGroupName + ':last ul' ).append( thisLi ); - } else { - $('
      • ') - .appendTo( this.list ) - .find( 'ul' ) - .append( thisLi ); - } - } else { - thisLi.appendTo(this.list); - } - - // append icon if option is specified - if (o.icons) { - for (var j in o.icons) { - if (thisLi.is(o.icons[j].find)) { - thisLi - .data('optionClasses', selectOptionData[i].classes + ' ' + self.widgetBaseClass + '-hasIcon') - .addClass(self.widgetBaseClass + '-hasIcon'); - var iconClass = o.icons[j].icon || ""; - thisLi - .find('a:eq(0)') - .prepend(''); - if (selectOptionData[i].bgImage) { - thisLi.find('span').css('background-image', selectOptionData[i].bgImage); - } - } - } - } - } - } else { - $('
      • ').appendTo(this.list); - } - // we need to set and unset the CSS classes for dropdown and popup style - var isDropDown = ( o.style == 'dropdown' ); - this.newelement - .toggleClass( self.widgetBaseClass + '-dropdown', isDropDown ) - .toggleClass( self.widgetBaseClass + '-popup', !isDropDown ); - this.list - .toggleClass( self.widgetBaseClass + '-menu-dropdown ui-corner-bottom', isDropDown ) - .toggleClass( self.widgetBaseClass + '-menu-popup ui-corner-all', !isDropDown ) - // add corners to top and bottom menu items - .find( 'li:first' ) - .toggleClass( 'ui-corner-top', !isDropDown ) - .end().find( 'li:last' ) - .addClass( 'ui-corner-bottom' ); - this.selectmenuIcon - .toggleClass( 'ui-icon-triangle-1-s', isDropDown ) - .toggleClass( 'ui-icon-triangle-2-n-s', !isDropDown ); - - // transfer classes to selectmenu and list - if ( o.transferClasses ) { - var transferClasses = this.element.attr( 'class' ) || ''; - this.newelement.add( this.list ).addClass( transferClasses ); - } - - // set menu width to either menuWidth option value, width option value, or select width - if ( o.style == 'dropdown' ) { - this.list.width( o.menuWidth ? o.menuWidth : o.width ); - } else { - this.list.width( o.menuWidth ? o.menuWidth : o.width - o.handleWidth ); - } - - // reset height to auto - this.list.css( 'height', 'auto' ); - var listH = this.listWrap.height(); - // calculate default max height - if ( o.maxHeight && o.maxHeight < listH ) { - this.list.height( o.maxHeight ); - } else { - var winH = $( window ).height() / 3; - if ( winH < listH ) this.list.height( winH ); - } - - // save reference to actionable li's (not group label li's) - this._optionLis = this.list.find( 'li:not(.' + self.widgetBaseClass + '-group)' ); - - // transfer disabled state - if ( this.element.attr( 'disabled' ) ) { - this.disable(); - } else { - this.enable() - } - - // update value - this.index( this._selectedIndex() ); - - // needed when selectmenu is placed at the very bottom / top of the page - window.setTimeout( function() { - self._refreshPosition(); - }, 200 ); - }, - - destroy: function() { - this.element.removeData( this.widgetName ) - .removeClass( this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled' ) - .removeAttr( 'aria-disabled' ) - .unbind( ".selectmenu" ); - - // TODO unneded as event binding has been disabled - // $( window ).unbind( ".selectmenu" ); - $( document ).unbind( ".selectmenu" ); - - // unbind click on label, reset its for attr - $( 'label[for=' + this.newelement.attr('id') + ']' ) - .attr( 'for', this.element.attr( 'id' ) ) - .unbind( '.selectmenu' ); - - this.newelementWrap.remove(); - this.listWrap.remove(); - - this.element.show(); - - // call widget destroy function - $.Widget.prototype.destroy.apply(this, arguments); - }, - - _typeAhead: function( code, eventType ){ - var self = this, focusFound = false, C = String.fromCharCode(code).toUpperCase(); - c = C.toLowerCase(); - - if ( self.options.typeAhead == 'sequential' ) { - // clear the timeout so we can use _prevChar - window.clearTimeout('ui.selectmenu-' + self.selectmenuId); - - // define our find var - var find = typeof( self._prevChar ) == 'undefined' ? '' : self._prevChar.join( '' ); - - function focusOptSeq( elem, ind, c ){ - focusFound = true; - $( elem ).trigger( eventType ); - typeof( self._prevChar ) == 'undefined' ? self._prevChar = [ c ] : self._prevChar[ self._prevChar.length ] = c; - } - this.list.find( 'li a' ).each( function( i ) { - if ( !focusFound ) { - // allow the typeahead attribute on the option tag for a more specific lookup - var thisText = $( this ).attr( 'typeahead' ) || $(this).text(); - if ( thisText.indexOf( find + C ) === 0 ) { - focusOptSeq( this, i, C ); - } else if (thisText.indexOf(find+c) === 0 ) { - focusOptSeq( this, i, c ); - } - } - }); - // set a 1 second timeout for sequenctial typeahead - // keep this set even if we have no matches so it doesnt typeahead somewhere else - window.setTimeout( function( el ) { - self._prevChar = undefined; - }, 1000, self ); - - } else { - // define self._prevChar if needed - if ( !self._prevChar ) { self._prevChar = [ '' , 0 ]; } - - focusFound = false; - function focusOpt( elem, ind ){ - focusFound = true; - $( elem ).trigger( eventType ); - self._prevChar[ 1 ] = ind; - } - this.list.find( 'li a' ).each(function( i ){ - if (!focusFound){ - var thisText = $(this).text(); - if ( thisText.indexOf( C ) === 0 || thisText.indexOf( c ) === 0 ) { - if (self._prevChar[0] == C){ - if ( self._prevChar[ 1 ] < i ){ focusOpt( this, i ); } - } else{ - focusOpt( this, i ); - } - } - } - }); - this._prevChar[ 0 ] = C; - } - }, - - // returns some usefull information, called by callbacks only - _uiHash: function() { - var index = this.index(); - return { - index: index, - option: $("option", this.element).get(index), - value: this.element[0].value - }; - }, - - open: function(event) { - var self = this, o = this.options; - if ( self.newelement.attr("aria-disabled") != 'true' ) { - self._closeOthers(event); - self.newelement.addClass('ui-state-active'); - - self.listWrap.appendTo( o.appendTo ); - self.list.attr('aria-hidden', false); - - if ( o.style == "dropdown" ) { - self.newelement.removeClass('ui-corner-all').addClass('ui-corner-top'); - } - - self.listWrap.addClass( self.widgetBaseClass + '-open' ); - // positioning needed for IE7 (tested 01.08.11 on MS VPC Image) - // see https://github.com/fnagel/jquery-ui/issues/147 - if ( $.browser.msie && $.browser.version.substr( 0,1 ) == 7 ) { - self._refreshPosition(); - } - var selected = self.list.attr('aria-hidden', false).find('li:not(.' + self.widgetBaseClass + '-group):eq(' + self._selectedIndex() + '):visible a'); - if (selected.length) selected[0].focus(); - // positioning needed for FF, Chrome, IE8, IE7, IE6 (tested 01.08.11 on MS VPC Image) - self._refreshPosition(); - - self._trigger("open", event, self._uiHash()); - } - }, - - close: function(event, retainFocus) { - if ( this.newelement.is('.ui-state-active') ) { - this.newelement - .removeClass('ui-state-active'); - this.listWrap.removeClass(this.widgetBaseClass + '-open'); - this.list.attr('aria-hidden', true); - if ( this.options.style == "dropdown" ) { - this.newelement.removeClass('ui-corner-top').addClass('ui-corner-all'); - } - if ( retainFocus ) { - this.newelement.focus(); - } - this._trigger("close", event, this._uiHash()); - } - }, - - change: function(event) { - this.element.trigger("change"); - this._trigger("change", event, this._uiHash()); - }, - - select: function(event) { - if (this._disabled(event.currentTarget)) { return false; } - this._trigger("select", event, this._uiHash()); - }, - - _closeOthers: function(event) { - $('.' + this.widgetBaseClass + '.ui-state-active').not(this.newelement).each(function() { - $(this).data('selectelement').selectmenu('close', event); - }); - $('.' + this.widgetBaseClass + '.ui-state-hover').trigger('mouseout'); - }, - - _toggle: function(event, retainFocus) { - if ( this.list.parent().is('.' + this.widgetBaseClass + '-open') ) { - this.close(event, retainFocus); - } else { - this.open(event); - } - }, - - _formatText: function(text) { - return (this.options.format ? this.options.format(text) : text); - }, - - _selectedIndex: function() { - return this.element[0].selectedIndex; - }, - - _selectedOptionLi: function() { - return this._optionLis.eq(this._selectedIndex()); - }, - - _focusedOptionLi: function() { - return this.list.find('.' + this.widgetBaseClass + '-item-focus'); - }, - - _moveSelection: function(amt, recIndex) { - // do nothing if disabled - if (!this.options.disabled) { - var currIndex = parseInt(this._selectedOptionLi().data('index') || 0, 10); - var newIndex = currIndex + amt; - // do not loop when using up key - - if (newIndex < 0) { - newIndex = 0; - } - if (newIndex > this._optionLis.size() - 1) { - newIndex = this._optionLis.size() - 1; - } - // Occurs when a full loop has been made - if (newIndex === recIndex) { return false; } - - if (this._optionLis.eq(newIndex).hasClass( this.namespace + '-state-disabled' )) { - // if option at newIndex is disabled, call _moveFocus, incrementing amt by one - (amt > 0) ? ++amt : --amt; - this._moveSelection(amt, newIndex); - } else { - return this._optionLis.eq(newIndex).trigger('mouseup'); - } - } - }, - - _moveFocus: function(amt, recIndex) { - if (!isNaN(amt)) { - var currIndex = parseInt(this._focusedOptionLi().data('index') || 0, 10); - var newIndex = currIndex + amt; - } else { - var newIndex = parseInt(this._optionLis.filter(amt).data('index'), 10); - } - - if (newIndex < 0) { - newIndex = 0; - } - if (newIndex > this._optionLis.size() - 1) { - newIndex = this._optionLis.size() - 1; - } - - //Occurs when a full loop has been made - if (newIndex === recIndex) { return false; } - - var activeID = this.widgetBaseClass + '-item-' + Math.round(Math.random() * 1000); - - this._focusedOptionLi().find('a:eq(0)').attr('id', ''); - - if (this._optionLis.eq(newIndex).hasClass( this.namespace + '-state-disabled' )) { - // if option at newIndex is disabled, call _moveFocus, incrementing amt by one - (amt > 0) ? ++amt : --amt; - this._moveFocus(amt, newIndex); - } else { - this._optionLis.eq(newIndex).find('a:eq(0)').attr('id',activeID).focus(); - } - - this.list.attr('aria-activedescendant', activeID); - }, - - _scrollPage: function(direction) { - var numPerPage = Math.floor(this.list.outerHeight() / this.list.find('li:first').outerHeight()); - numPerPage = (direction == 'up' ? -numPerPage : numPerPage); - this._moveFocus(numPerPage); - }, - - _setOption: function(key, value) { - this.options[key] = value; - // set - if (key == 'disabled') { - this.close(); - this.element - .add(this.newelement) - .add(this.list)[value ? 'addClass' : 'removeClass']( - this.widgetBaseClass + '-disabled' + ' ' + - this.namespace + '-state-disabled') - .attr("aria-disabled", value); - } - }, - - disable: function(index, type){ - // if options is not provided, call the parents disable function - if ( typeof( index ) == 'undefined' ) { - this._setOption( 'disabled', true ); - } else { - if ( type == "optgroup" ) { - this._disableOptgroup(index); - } else { - this._disableOption(index); - } - } - }, - - enable: function(index, type) { - // if options is not provided, call the parents enable function - if ( typeof( index ) == 'undefined' ) { - this._setOption('disabled', false); - } else { - if ( type == "optgroup" ) { - this._enableOptgroup(index); - } else { - this._enableOption(index); - } - } - }, - - _disabled: function(elem) { - return $(elem).hasClass( this.namespace + '-state-disabled' ); - }, - - - _disableOption: function(index) { - var optionElem = this._optionLis.eq(index); - if (optionElem) { - optionElem.addClass(this.namespace + '-state-disabled') - .find("a").attr("aria-disabled", true); - this.element.find("option").eq(index).attr("disabled", "disabled"); - } - }, - - _enableOption: function(index) { - var optionElem = this._optionLis.eq(index); - if (optionElem) { - optionElem.removeClass( this.namespace + '-state-disabled' ) - .find("a").attr("aria-disabled", false); - this.element.find("option").eq(index).removeAttr("disabled"); - } - }, - - _disableOptgroup: function(index) { - var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index ); - if (optGroupElem) { - optGroupElem.addClass(this.namespace + '-state-disabled') - .attr("aria-disabled", true); - this.element.find("optgroup").eq(index).attr("disabled", "disabled"); - } - }, - - _enableOptgroup: function(index) { - var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index ); - if (optGroupElem) { - optGroupElem.removeClass(this.namespace + '-state-disabled') - .attr("aria-disabled", false); - this.element.find("optgroup").eq(index).removeAttr("disabled"); - } - }, - - index: function(newValue) { - if (arguments.length) { - if (!this._disabled($(this._optionLis[newValue]))) { - this.element[0].selectedIndex = newValue; - this._refreshValue(); - } else { - return false; - } - } else { - return this._selectedIndex(); - } - }, - - value: function(newValue) { - if (arguments.length) { - this.element[0].value = newValue; - this._refreshValue(); - } else { - return this.element[0].value; - } - }, - - _refreshValue: function() { - var activeClass = (this.options.style == "popup") ? " ui-state-active" : ""; - var activeID = this.widgetBaseClass + '-item-' + Math.round(Math.random() * 1000); - // deselect previous - this.list - .find('.' + this.widgetBaseClass + '-item-selected') - .removeClass(this.widgetBaseClass + "-item-selected" + activeClass) - .find('a') - .attr('aria-selected', 'false') - .attr('id', ''); - // select new - this._selectedOptionLi() - .addClass(this.widgetBaseClass + "-item-selected" + activeClass) - .find('a') - .attr('aria-selected', 'true') - .attr('id', activeID); - - // toggle any class brought in from option - var currentOptionClasses = (this.newelement.data('optionClasses') ? this.newelement.data('optionClasses') : ""); - var newOptionClasses = (this._selectedOptionLi().data('optionClasses') ? this._selectedOptionLi().data('optionClasses') : ""); - this.newelement - .removeClass(currentOptionClasses) - .data('optionClasses', newOptionClasses) - .addClass( newOptionClasses ) - .find('.' + this.widgetBaseClass + '-status') - .html( - this._selectedOptionLi() - .find('a:eq(0)') - .html() - ); - - this.list.attr('aria-activedescendant', activeID); - }, - - _refreshPosition: function() { - var o = this.options; - - // if its a native pop-up we need to calculate the position of the selected li - if ( o.style == "popup" && !o.positionOptions.offset ) { - var selected = this._selectedOptionLi(); - var _offset = "0 -" + ( selected.outerHeight() + selected.offset().top - this.list.offset().top ); - } - // update zIndex if jQuery UI is able to process - var zIndexElement = this.element.zIndex(); - if ( zIndexElement ) { - this.listWrap.css( 'zIndex', zIndexElement ); - } - this.listWrap.position({ - // set options for position plugin - of: o.positionOptions.of || this.newelement, - my: o.positionOptions.my, - at: o.positionOptions.at, - offset: o.positionOptions.offset || _offset, - collision: o.positionOptions.collision || 'flip' - }); - } + getter: "value", + version: "1.8", + eventPrefix: "selectmenu", + options: { + transferClasses: true, + typeAhead: "sequential", + style: 'dropdown', + positionOptions: { + my: "left top", + at: "left bottom", + offset: null + }, + width: null, + menuWidth: null, + handleWidth: 26, + maxHeight: null, + icons: null, + format: null, + bgImage: function() {}, + wrapperElement: "
        " + }, + + _create: function() { + var self = this, o = this.options; + + // set a default id value, generate a new random one if not set by developer + var selectmenuId = this.element.attr( 'id' ) || 'ui-selectmenu-' + Math.random().toString( 16 ).slice( 2, 10 ); + + // quick array of button and menu id's + this.ids = [ selectmenuId + '-button', selectmenuId + '-menu' ]; + + // define safe mouseup for future toggling + this._safemouseup = true; + + // create menu button wrapper + this.newelement = $( '', { + 'class': this.widgetBaseClass + ' ui-widget ui-state-default ui-corner-all', + 'id' : this.ids[ 0 ], + 'role': 'button', + 'href': '#nogo', + 'tabindex': this.element.attr( 'disabled' ) ? 1 : 0, + 'aria-haspopup': true, + 'aria-owns': this.ids[ 1 ] + }); + this.newelementWrap = $( o.wrapperElement ) + .append( this.newelement ) + .insertAfter( this.element ); + + // transfer tabindex + var tabindex = this.element.attr( 'tabindex' ); + if ( tabindex ) { + this.newelement.attr( 'tabindex', tabindex ); + } + + // save reference to select in data for ease in calling methods + this.newelement.data( 'selectelement', this.element ); + + // menu icon + this.selectmenuIcon = $( '' ) + .prependTo( this.newelement ); + + // append status span to button + this.newelement.prepend( '' ); + + // make associated form label trigger focus + $( 'label[for="' + selectmenuId + '"]' ) + .attr( 'for', this.ids[0] ) + .bind( 'click.selectmenu', function() { + self.newelement[0].focus(); + return false; + }); + + // click toggle for menu visibility + this.newelement + .bind('mousedown.selectmenu', function(event) { + self._toggle(event, true); + // make sure a click won't open/close instantly + if (o.style == "popup") { + self._safemouseup = false; + setTimeout(function() { self._safemouseup = true; }, 300); + } + return false; + }) + .bind('click.selectmenu', function() { + return false; + }) + .bind("keydown.selectmenu", function(event) { + var ret = false; + switch (event.keyCode) { + case $.ui.keyCode.ENTER: + ret = true; + break; + case $.ui.keyCode.SPACE: + self._toggle(event); + break; + case $.ui.keyCode.UP: + if (event.altKey) { + self.open(event); + } else { + self._moveSelection(-1); + } + break; + case $.ui.keyCode.DOWN: + if (event.altKey) { + self.open(event); + } else { + self._moveSelection(1); + } + break; + case $.ui.keyCode.LEFT: + self._moveSelection(-1); + break; + case $.ui.keyCode.RIGHT: + self._moveSelection(1); + break; + case $.ui.keyCode.TAB: + ret = true; + break; + default: + ret = true; + } + return ret; + }) + .bind('keypress.selectmenu', function(event) { + self._typeAhead(event.which, 'mouseup'); + return true; + }) + .bind('mouseover.selectmenu focus.selectmenu', function() { + if (!o.disabled) { + $(this).addClass(self.widgetBaseClass + '-focus ui-state-hover'); + } + }) + .bind('mouseout.selectmenu blur.selectmenu', function() { + if (!o.disabled) { + $(this).removeClass(self.widgetBaseClass + '-focus ui-state-hover'); + } + }); + + // document click closes menu + $(document).bind("mousedown.selectmenu", function(event) { + self.close(event); + }); + + // change event on original selectmenu + this.element + .bind("click.selectmenu", function() { + self._refreshValue(); + }) + // FIXME: newelement can be null under unclear circumstances in IE8 + // TODO not sure if this is still a problem (fnagel 20.03.11) + .bind("focus.selectmenu", function() { + if (self.newelement) { + self.newelement[0].focus(); + } + }); + + // set width when not set via options + if (!o.width) { + o.width = this.element.outerWidth(); + } + // set menu button width + this.newelement.width(o.width); + + // hide original selectmenu element + this.element.hide(); + + // create menu portion, append to body + this.list = $( '
          ', { + 'class': 'ui-widget ui-widget-content', + 'aria-hidden': true, + 'role': 'listbox', + 'aria-labelledby': this.ids[0], + 'id': this.ids[1] + }); + this.listWrap = $( o.wrapperElement ) + .addClass( self.widgetBaseClass + '-menu' ) + .append( this.list ) + .appendTo( 'body' ); + + // transfer menu click to menu button + this.list + .bind("keydown.selectmenu", function(event) { + var ret = false; + switch (event.keyCode) { + case $.ui.keyCode.UP: + if (event.altKey) { + self.close(event, true); + } else { + self._moveFocus(-1); + } + break; + case $.ui.keyCode.DOWN: + if (event.altKey) { + self.close(event, true); + } else { + self._moveFocus(1); + } + break; + case $.ui.keyCode.LEFT: + self._moveFocus(-1); + break; + case $.ui.keyCode.RIGHT: + self._moveFocus(1); + break; + case $.ui.keyCode.HOME: + self._moveFocus(':first'); + break; + case $.ui.keyCode.PAGE_UP: + self._scrollPage('up'); + break; + case $.ui.keyCode.PAGE_DOWN: + self._scrollPage('down'); + break; + case $.ui.keyCode.END: + self._moveFocus(':last'); + break; + case $.ui.keyCode.ENTER: + case $.ui.keyCode.SPACE: + self.close(event, true); + $(event.target).parents('li:eq(0)').trigger('mouseup'); + break; + case $.ui.keyCode.TAB: + ret = true; + self.close(event, true); + $(event.target).parents('li:eq(0)').trigger('mouseup'); + break; + case $.ui.keyCode.ESCAPE: + self.close(event, true); + break; + default: + ret = true; + } + return ret; + }) + .bind('keypress.selectmenu', function(event) { + self._typeAhead(event.which, 'focus'); + return true; + }) + // this allows for using the scrollbar in an overflowed list + .bind( 'mousedown.selectmenu mouseup.selectmenu', function() { return false; }); + + // needed when window is resized + // TODO seems to be useless, but causes errors (fnagel 01.08.11) + // see: https://github.com/fnagel/jquery-ui/issues/147 + // $(window).bind( "resize.selectmenu", $.proxy( self._refreshPosition, this ) ); + }, + + _init: function() { + var self = this, o = this.options; + + // serialize selectmenu element options + var selectOptionData = []; + this.element + .find('option') + .each(function() { + var opt = $(this); + selectOptionData.push({ + value: opt.attr('value'), + text: self._formatText(opt.text()), + selected: opt.attr('selected'), + disabled: opt.attr('disabled'), + classes: opt.attr('class'), + typeahead: opt.attr('typeahead'), + parentOptGroup: opt.parent('optgroup'), + bgImage: o.bgImage.call(opt) + }); + }); + + // active state class is only used in popup style + var activeClass = (self.options.style == "popup") ? " ui-state-active" : ""; + + // empty list so we can refresh the selectmenu via selectmenu() + this.list.html(""); + + // write li's + if (selectOptionData.length) { + for (var i = 0; i < selectOptionData.length; i++) { + var thisLiAttr = { role : 'presentation' }; + if ( selectOptionData[ i ].disabled ) { + thisLiAttr[ 'class' ] = this.namespace + '-state-disabled'; + } + var thisAAttr = { + html: selectOptionData[i].text, + href : '#nogo', + tabindex : -1, + role : 'option', + 'aria-selected' : false + }; + if ( selectOptionData[ i ].disabled ) { + thisAAttr[ 'aria-disabled' ] = selectOptionData[ i ].disabled; + } + if ( selectOptionData[ i ].typeahead ) { + thisAAttr[ 'typeahead' ] = selectOptionData[ i ].typeahead; + } + var thisA = $('', thisAAttr); + var thisLi = $('
        • ', thisLiAttr) + .append(thisA) + .data('index', i) + .addClass(selectOptionData[i].classes) + .data('optionClasses', selectOptionData[i].classes || '') + .bind("mouseup.selectmenu", function(event) { + if (self._safemouseup && !self._disabled(event.currentTarget) && !self._disabled($( event.currentTarget ).parents( "ul>li." + self.widgetBaseClass + "-group " )) ) { + var changed = $(this).data('index') != self._selectedIndex(); + self.index($(this).data('index')); + self.select(event); + if (changed) { + self.change(event); + } + self.close(event, true); + } + return false; + }) + .bind("click.selectmenu", function() { + return false; + }) + .bind('mouseover.selectmenu focus.selectmenu', function(e) { + // no hover if diabled + if (!$(e.currentTarget).hasClass(self.namespace + '-state-disabled') && !$(e.currentTarget).parent("ul").parent("li").hasClass(self.namespace + '-state-disabled')) { + self._selectedOptionLi().addClass(activeClass); + self._focusedOptionLi().removeClass(self.widgetBaseClass + '-item-focus ui-state-hover'); + $(this).removeClass('ui-state-active').addClass(self.widgetBaseClass + '-item-focus ui-state-hover'); + } + }) + .bind('mouseout.selectmenu blur.selectmenu', function() { + if ($(this).is(self._selectedOptionLi().selector)) { + $(this).addClass(activeClass); + } + $(this).removeClass(self.widgetBaseClass + '-item-focus ui-state-hover'); + }); + + // optgroup or not... + if ( selectOptionData[i].parentOptGroup.length ) { + var optGroupName = self.widgetBaseClass + '-group-' + this.element.find( 'optgroup' ).index( selectOptionData[i].parentOptGroup ); + if (this.list.find( 'li.' + optGroupName ).length ) { + this.list.find( 'li.' + optGroupName + ':last ul' ).append( thisLi ); + } else { + $('
        • ') + .appendTo( this.list ) + .find( 'ul' ) + .append( thisLi ); + } + } else { + thisLi.appendTo(this.list); + } + + // append icon if option is specified + if (o.icons) { + for (var j in o.icons) { + if (thisLi.is(o.icons[j].find)) { + thisLi + .data('optionClasses', selectOptionData[i].classes + ' ' + self.widgetBaseClass + '-hasIcon') + .addClass(self.widgetBaseClass + '-hasIcon'); + var iconClass = o.icons[j].icon || ""; + thisLi + .find('a:eq(0)') + .prepend(''); + if (selectOptionData[i].bgImage) { + thisLi.find('span').css('background-image', selectOptionData[i].bgImage); + } + } + } + } + } + } else { + $('
        • ').appendTo(this.list); + } + // we need to set and unset the CSS classes for dropdown and popup style + var isDropDown = ( o.style == 'dropdown' ); + this.newelement + .toggleClass( self.widgetBaseClass + '-dropdown', isDropDown ) + .toggleClass( self.widgetBaseClass + '-popup', !isDropDown ); + this.list + .toggleClass( self.widgetBaseClass + '-menu-dropdown ui-corner-bottom', isDropDown ) + .toggleClass( self.widgetBaseClass + '-menu-popup ui-corner-all', !isDropDown ) + // add corners to top and bottom menu items + .find( 'li:first' ) + .toggleClass( 'ui-corner-top', !isDropDown ) + .end().find( 'li:last' ) + .addClass( 'ui-corner-bottom' ); + this.selectmenuIcon + .toggleClass( 'ui-icon-triangle-1-s', isDropDown ) + .toggleClass( 'ui-icon-triangle-2-n-s', !isDropDown ); + + // transfer classes to selectmenu and list + if ( o.transferClasses ) { + var transferClasses = this.element.attr( 'class' ) || ''; + this.newelement.add( this.list ).addClass( transferClasses ); + } + + // set menu width to either menuWidth option value, width option value, or select width + if ( o.style == 'dropdown' ) { + this.list.width( o.menuWidth ? o.menuWidth : o.width ); + } else { + this.list.width( o.menuWidth ? o.menuWidth : o.width - o.handleWidth ); + } + + // reset height to auto + this.list.css( 'height', 'auto' ); + var listH = this.listWrap.height(); + // calculate default max height + if ( o.maxHeight && o.maxHeight < listH ) { + this.list.height( o.maxHeight ); + } else { + var winH = $( window ).height() / 3; + if ( winH < listH ) this.list.height( winH ); + } + + // save reference to actionable li's (not group label li's) + this._optionLis = this.list.find( 'li:not(.' + self.widgetBaseClass + '-group)' ); + + // transfer disabled state + if ( this.element.attr( 'disabled' ) ) { + this.disable(); + } else { + this.enable() + } + + // update value + this.index( this._selectedIndex() ); + + // needed when selectmenu is placed at the very bottom / top of the page + window.setTimeout( function() { + self._refreshPosition(); + }, 200 ); + }, + + destroy: function() { + this.element.removeData( this.widgetName ) + .removeClass( this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled' ) + .removeAttr( 'aria-disabled' ) + .unbind( ".selectmenu" ); + + // TODO unneded as event binding has been disabled + // $( window ).unbind( ".selectmenu" ); + $( document ).unbind( ".selectmenu" ); + + // unbind click on label, reset its for attr + $( 'label[for=' + this.newelement.attr('id') + ']' ) + .attr( 'for', this.element.attr( 'id' ) ) + .unbind( '.selectmenu' ); + + this.newelementWrap.remove(); + this.listWrap.remove(); + + this.element.show(); + + // call widget destroy function + $.Widget.prototype.destroy.apply(this, arguments); + }, + + _typeAhead: function( code, eventType ){ + var self = this, focusFound = false, C = String.fromCharCode(code).toUpperCase(); + c = C.toLowerCase(); + + if ( self.options.typeAhead == 'sequential' ) { + // clear the timeout so we can use _prevChar + window.clearTimeout('ui.selectmenu-' + self.selectmenuId); + + // define our find var + var find = typeof( self._prevChar ) == 'undefined' ? '' : self._prevChar.join( '' ); + + function focusOptSeq( elem, ind, c ){ + focusFound = true; + $( elem ).trigger( eventType ); + typeof( self._prevChar ) == 'undefined' ? self._prevChar = [ c ] : self._prevChar[ self._prevChar.length ] = c; + } + this.list.find( 'li a' ).each( function( i ) { + if ( !focusFound ) { + // allow the typeahead attribute on the option tag for a more specific lookup + var thisText = $( this ).attr( 'typeahead' ) || $(this).text(); + if ( thisText.indexOf( find + C ) === 0 ) { + focusOptSeq( this, i, C ); + } else if (thisText.indexOf(find+c) === 0 ) { + focusOptSeq( this, i, c ); + } + } + }); + // set a 1 second timeout for sequenctial typeahead + // keep this set even if we have no matches so it doesnt typeahead somewhere else + window.setTimeout( function( el ) { + self._prevChar = undefined; + }, 1000, self ); + + } else { + // define self._prevChar if needed + if ( !self._prevChar ) { self._prevChar = [ '' , 0 ]; } + + focusFound = false; + function focusOpt( elem, ind ){ + focusFound = true; + $( elem ).trigger( eventType ); + self._prevChar[ 1 ] = ind; + } + this.list.find( 'li a' ).each(function( i ){ + if (!focusFound){ + var thisText = $(this).text(); + if ( thisText.indexOf( C ) === 0 || thisText.indexOf( c ) === 0 ) { + if (self._prevChar[0] == C){ + if ( self._prevChar[ 1 ] < i ){ focusOpt( this, i ); } + } else{ + focusOpt( this, i ); + } + } + } + }); + this._prevChar[ 0 ] = C; + } + }, + + // returns some usefull information, called by callbacks only + _uiHash: function() { + var index = this.index(); + return { + index: index, + option: $("option", this.element).get(index), + value: this.element[0].value + }; + }, + + open: function(event) { + var self = this, o = this.options; + if ( self.newelement.attr("aria-disabled") != 'true' ) { + self._closeOthers(event); + self.newelement.addClass('ui-state-active'); + + self.listWrap.appendTo( o.appendTo ); + self.list.attr('aria-hidden', false); + + if ( o.style == "dropdown" ) { + self.newelement.removeClass('ui-corner-all').addClass('ui-corner-top'); + } + + self.listWrap.addClass( self.widgetBaseClass + '-open' ); + // positioning needed for IE7 (tested 01.08.11 on MS VPC Image) + // see https://github.com/fnagel/jquery-ui/issues/147 + if ( $.browser.msie && $.browser.version.substr( 0,1 ) == 7 ) { + self._refreshPosition(); + } + var selected = self.list.attr('aria-hidden', false).find('li:not(.' + self.widgetBaseClass + '-group):eq(' + self._selectedIndex() + '):visible a'); + if (selected.length) selected[0].focus(); + // positioning needed for FF, Chrome, IE8, IE7, IE6 (tested 01.08.11 on MS VPC Image) + self._refreshPosition(); + + self._trigger("open", event, self._uiHash()); + } + }, + + close: function(event, retainFocus) { + if ( this.newelement.is('.ui-state-active') ) { + this.newelement + .removeClass('ui-state-active'); + this.listWrap.removeClass(this.widgetBaseClass + '-open'); + this.list.attr('aria-hidden', true); + if ( this.options.style == "dropdown" ) { + this.newelement.removeClass('ui-corner-top').addClass('ui-corner-all'); + } + if ( retainFocus ) { + this.newelement.focus(); + } + this._trigger("close", event, this._uiHash()); + } + }, + + change: function(event) { + this.element.trigger("change"); + this._trigger("change", event, this._uiHash()); + }, + + select: function(event) { + if (this._disabled(event.currentTarget)) { return false; } + this._trigger("select", event, this._uiHash()); + }, + + _closeOthers: function(event) { + $('.' + this.widgetBaseClass + '.ui-state-active').not(this.newelement).each(function() { + $(this).data('selectelement').selectmenu('close', event); + }); + $('.' + this.widgetBaseClass + '.ui-state-hover').trigger('mouseout'); + }, + + _toggle: function(event, retainFocus) { + if ( this.list.parent().is('.' + this.widgetBaseClass + '-open') ) { + this.close(event, retainFocus); + } else { + this.open(event); + } + }, + + _formatText: function(text) { + return (this.options.format ? this.options.format(text) : text); + }, + + _selectedIndex: function() { + return this.element[0].selectedIndex; + }, + + _selectedOptionLi: function() { + return this._optionLis.eq(this._selectedIndex()); + }, + + _focusedOptionLi: function() { + return this.list.find('.' + this.widgetBaseClass + '-item-focus'); + }, + + _moveSelection: function(amt, recIndex) { + // do nothing if disabled + if (!this.options.disabled) { + var currIndex = parseInt(this._selectedOptionLi().data('index') || 0, 10); + var newIndex = currIndex + amt; + // do not loop when using up key + + if (newIndex < 0) { + newIndex = 0; + } + if (newIndex > this._optionLis.size() - 1) { + newIndex = this._optionLis.size() - 1; + } + // Occurs when a full loop has been made + if (newIndex === recIndex) { return false; } + + if (this._optionLis.eq(newIndex).hasClass( this.namespace + '-state-disabled' )) { + // if option at newIndex is disabled, call _moveFocus, incrementing amt by one + (amt > 0) ? ++amt : --amt; + this._moveSelection(amt, newIndex); + } else { + return this._optionLis.eq(newIndex).trigger('mouseup'); + } + } + }, + + _moveFocus: function(amt, recIndex) { + if (!isNaN(amt)) { + var currIndex = parseInt(this._focusedOptionLi().data('index') || 0, 10); + var newIndex = currIndex + amt; + } else { + var newIndex = parseInt(this._optionLis.filter(amt).data('index'), 10); + } + + if (newIndex < 0) { + newIndex = 0; + } + if (newIndex > this._optionLis.size() - 1) { + newIndex = this._optionLis.size() - 1; + } + + //Occurs when a full loop has been made + if (newIndex === recIndex) { return false; } + + var activeID = this.widgetBaseClass + '-item-' + Math.round(Math.random() * 1000); + + this._focusedOptionLi().find('a:eq(0)').attr('id', ''); + + if (this._optionLis.eq(newIndex).hasClass( this.namespace + '-state-disabled' )) { + // if option at newIndex is disabled, call _moveFocus, incrementing amt by one + (amt > 0) ? ++amt : --amt; + this._moveFocus(amt, newIndex); + } else { + this._optionLis.eq(newIndex).find('a:eq(0)').attr('id',activeID).focus(); + } + + this.list.attr('aria-activedescendant', activeID); + }, + + _scrollPage: function(direction) { + var numPerPage = Math.floor(this.list.outerHeight() / this.list.find('li:first').outerHeight()); + numPerPage = (direction == 'up' ? -numPerPage : numPerPage); + this._moveFocus(numPerPage); + }, + + _setOption: function(key, value) { + this.options[key] = value; + // set + if (key == 'disabled') { + this.close(); + this.element + .add(this.newelement) + .add(this.list)[value ? 'addClass' : 'removeClass']( + this.widgetBaseClass + '-disabled' + ' ' + + this.namespace + '-state-disabled') + .attr("aria-disabled", value); + } + }, + + disable: function(index, type){ + // if options is not provided, call the parents disable function + if ( typeof( index ) == 'undefined' ) { + this._setOption( 'disabled', true ); + } else { + if ( type == "optgroup" ) { + this._disableOptgroup(index); + } else { + this._disableOption(index); + } + } + }, + + enable: function(index, type) { + // if options is not provided, call the parents enable function + if ( typeof( index ) == 'undefined' ) { + this._setOption('disabled', false); + } else { + if ( type == "optgroup" ) { + this._enableOptgroup(index); + } else { + this._enableOption(index); + } + } + }, + + _disabled: function(elem) { + return $(elem).hasClass( this.namespace + '-state-disabled' ); + }, + + _disableOption: function(index) { + var optionElem = this._optionLis.eq(index); + if (optionElem) { + optionElem.addClass(this.namespace + '-state-disabled') + .find("a").attr("aria-disabled", true); + this.element.find("option").eq(index).attr("disabled", "disabled"); + } + }, + + _enableOption: function(index) { + var optionElem = this._optionLis.eq(index); + if (optionElem) { + optionElem.removeClass( this.namespace + '-state-disabled' ) + .find("a").attr("aria-disabled", false); + this.element.find("option").eq(index).removeAttr("disabled"); + } + }, + + _disableOptgroup: function(index) { + var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index ); + if (optGroupElem) { + optGroupElem.addClass(this.namespace + '-state-disabled') + .attr("aria-disabled", true); + this.element.find("optgroup").eq(index).attr("disabled", "disabled"); + } + }, + + _enableOptgroup: function(index) { + var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index ); + if (optGroupElem) { + optGroupElem.removeClass(this.namespace + '-state-disabled') + .attr("aria-disabled", false); + this.element.find("optgroup").eq(index).removeAttr("disabled"); + } + }, + + index: function(newValue) { + if (arguments.length) { + if (!this._disabled($(this._optionLis[newValue]))) { + this.element[0].selectedIndex = newValue; + this._refreshValue(); + } else { + return false; + } + } else { + return this._selectedIndex(); + } + }, + + value: function(newValue) { + if (arguments.length) { + this.element[0].value = newValue; + this._refreshValue(); + } else { + return this.element[0].value; + } + }, + + _refreshValue: function() { + var activeClass = (this.options.style == "popup") ? " ui-state-active" : ""; + var activeID = this.widgetBaseClass + '-item-' + Math.round(Math.random() * 1000); + // deselect previous + this.list + .find('.' + this.widgetBaseClass + '-item-selected') + .removeClass(this.widgetBaseClass + "-item-selected" + activeClass) + .find('a') + .attr('aria-selected', 'false') + .attr('id', ''); + // select new + this._selectedOptionLi() + .addClass(this.widgetBaseClass + "-item-selected" + activeClass) + .find('a') + .attr('aria-selected', 'true') + .attr('id', activeID); + + // toggle any class brought in from option + var currentOptionClasses = (this.newelement.data('optionClasses') ? this.newelement.data('optionClasses') : ""); + var newOptionClasses = (this._selectedOptionLi().data('optionClasses') ? this._selectedOptionLi().data('optionClasses') : ""); + this.newelement + .removeClass(currentOptionClasses) + .data('optionClasses', newOptionClasses) + .addClass( newOptionClasses ) + .find('.' + this.widgetBaseClass + '-status') + .html( + this._selectedOptionLi() + .find('a:eq(0)') + .html() + ); + + this.list.attr('aria-activedescendant', activeID); + }, + + _refreshPosition: function() { + var o = this.options; + + // if its a native pop-up we need to calculate the position of the selected li + if ( o.style == "popup" && !o.positionOptions.offset ) { + var selected = this._selectedOptionLi(); + var _offset = "0 -" + ( selected.outerHeight() + selected.offset().top - this.list.offset().top ); + } + // update zIndex if jQuery UI is able to process + var zIndexElement = this.element.zIndex(); + if ( zIndexElement ) { + this.listWrap.css( 'zIndex', zIndexElement ); + } + this.listWrap.position({ + // set options for position plugin + of: o.positionOptions.of || this.newelement, + my: o.positionOptions.my, + at: o.positionOptions.at, + offset: o.positionOptions.offset || _offset, + collision: o.positionOptions.collision || 'flip' + }); + } }); })(jQuery); diff --git a/app/assets/javascripts/projects.js b/app/assets/javascripts/projects.js index 74f0e643..87be2f07 100644 --- a/app/assets/javascripts/projects.js +++ b/app/assets/javascripts/projects.js @@ -8,7 +8,7 @@ $(document).ready(function(){ e.stopPropagation(); $(this).find("td.tree-item-file-name a").click(); return false; - } + } }); $("#projects-list .project").live('click', function(e){ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 42fe63db..db803ee4 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -3,5 +3,5 @@ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at * the top of the compiled file, but it's generally better to create a new file per style scope. *= require_self - *= require_tree . + *= require_tree . */ diff --git a/app/assets/stylesheets/highlight.css.scss b/app/assets/stylesheets/highlight.css.scss index 31f9369a..fc14949a 100644 --- a/app/assets/stylesheets/highlight.css.scss +++ b/app/assets/stylesheets/highlight.css.scss @@ -1,4 +1,4 @@ -@mixin round-borders-all($radius) { +@mixin round-borders-all($radius) { border: 1px solid #eaeaea; -moz-border-radius: $radius; -webkit-border-radius: $radius; @@ -28,11 +28,11 @@ td.linenos{ .highlight pre{ } -.linenodiv pre { +.linenodiv pre { white-space:pre-line; } -td.linenos { +td.linenos { background:#ECECEC; color:#777; padding:10px 0px 0px 10px; @@ -42,7 +42,7 @@ td.linenos { } -td.code .highlight { +td.code .highlight { overflow: auto; } table.highlighttable pre{ @@ -53,9 +53,8 @@ table.highlighttable pre{ text-align:left; } - .git-empty .highlight { - @include round-borders-all(4px); + @include round-borders-all(4px); background:#eee; padding:5px; //overflow-x:scroll; @@ -71,10 +70,9 @@ table.highlighttable pre{ .shadow{ -webkit-box-shadow:0 5px 15px #000; -moz-box-shadow:0 5px 15px #000; - box-shadow:0 5px 15px #000; + box-shadow:0 5px 15px #000; } - .hll { background-color: #ffffff } .c { color: #888888; font-style: italic } /* Comment */ .err { color: #a61717; background-color: #e3d2d2 } /* Error */ @@ -105,7 +103,7 @@ table.highlighttable pre{ .highlight .nb{color:#0086B3;} /* Name.Builtin */ .highlight .nc{color:#458;font-weight:bold;} /* Name.Class */ .highlight .no{color:#008080;} /* Name.Constant */ -.highlight .ni{color:#800080;} +.highlight .ni{color:#800080;} .highlight .ne{color:#900;font-weight:bold;} /* Name.Exception */ .highlight .nf{color:#900;font-weight:bold;} /* Name.Function */ .highlight .nn{color:#005;font-weight:bold;} /* Name.Namespace */ diff --git a/app/assets/stylesheets/jquery.ui.selectmenu.css b/app/assets/stylesheets/jquery.ui.selectmenu.css index 37cfbd05..481adf5a 100644 --- a/app/assets/stylesheets/jquery.ui.selectmenu.css +++ b/app/assets/stylesheets/jquery.ui.selectmenu.css @@ -3,7 +3,7 @@ .ui-selectmenu { background:none; font-size:12px;display: block; display: inline-block; position: relative; height: 2.2em; vertical-align: middle; text-decoration: none; overflow: hidden; zoom: 1; } .ui-selectmenu-icon { position:absolute; right:6px; margin-top:-8px; top: 50%; } .ui-selectmenu-menu { padding:0; margin:0; position:absolute; top: 0; display: none; z-index: 1005;} /* z-index: 1005 to make selectmenu work with dialog */ -.ui-selectmenu-menu ul { padding:0; margin:0; list-style:none; position: relative; overflow: auto; overflow-y: auto ; overflow-x: hidden; } +.ui-selectmenu-menu ul { padding:0; margin:0; list-style:none; position: relative; overflow: auto; overflow-y: auto ; overflow-x: hidden; } .ui-selectmenu-open { display: block; } .ui-selectmenu.ui-widget { background:none; } .ui-selectmenu-menu-popup { margin-top: -1px; } diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 3e7633a6..6fd5150e 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -2,7 +2,7 @@ // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ -@mixin round-borders-bottom($radius) { +@mixin round-borders-bottom($radius) { border-top: 1px solid #eaeaea; -moz-border-radius-bottomright: $radius; @@ -15,7 +15,7 @@ -webkit-border-bottom-right-radius: $radius; } -@mixin round-borders-top($radius) { +@mixin round-borders-top($radius) { border-top: 1px solid #eaeaea; -moz-border-radius-topright: $radius; @@ -28,14 +28,14 @@ -webkit-border-top-right-radius: $radius; } -@mixin round-borders-all($radius) { +@mixin round-borders-all($radius) { border: 1px solid #eaeaea; -moz-border-radius: $radius; -webkit-border-radius: $radius; border-radius: $radius; } -@mixin hover-color { +@mixin hover-color { background: #fff !important; background: -webkit-gradient(linear,left top,left bottom,from(#fff),to(#FFF6BF)) !important; background: -moz-linear-gradient(top,#fff,#FFF6BF) !important; @@ -46,47 +46,47 @@ border:1px solid #CCC; margin-bottom:1em; - .diff_file_header { + .diff_file_header { padding:5px 5px; border-bottom:1px solid #CCC; background: #eee; } - .diff_file_content { + .diff_file_content { overflow-x: scroll; background:#fff; color:#333; font-size: 12px; font-family: 'Courier New', 'andale mono','lucida console',monospace; } - .diff_file_content_image { + .diff_file_content_image { background:#eee; text-align:center; - img { + img { padding:100px; max-width:300px; } } } -#logo { - &:hover { +#logo { + &:hover { background:none; } } -.file_stats { +.file_stats { margin-bottom:10px; @include round-borders-all(4px); - span { + span { border-top: 1px solid #eaeaea; padding:5px 5px; display:block; - &:first-child { + &:first-child { border-top:none; } - img { + img { width:18px; float:left; margin-right: 6px; @@ -94,15 +94,15 @@ } } -.round-borders { +.round-borders { @include round-borders-all(4px); padding: 4px 0px; } -table.round-borders { +table.round-borders { float:left; } -.day-commits-table { +.day-commits-table { @include round-borders-all(4px); padding: 4px 0px; margin-bottom:10px; @@ -110,55 +110,54 @@ table.round-borders { width:100%; background: #E6F1F6; - .day-header { + .day-header { padding:10px; h3 { margin:0px; } } - ul { + ul { display:block; list-style:none; margin:0px; padding:0px; - li.commit { + li.commit { display:list-item; padding:8px; margin:0px; background: #F7FBFC; border-top: 1px solid #E2EAEE; - &:first-child { + &:first-child { border-top: 1px solid #E2EAEE; } &:nth-child(2n+1) { background: white; } - a.button { + a.button { width:85px; padding:10px; margin:0px; float:right; } - p { + p { margin-bottom: 3px; font-size: 13px; } } } } -@mixin panel-color { +@mixin panel-color { background: #111 !important; background: -webkit-gradient(linear,left top,left bottom,from(#333),to(#111)) !important; background: -moz-linear-gradient(top,#333,#111) !important; background: transparent 9 !important; } - -#header-panel { +#header-panel { @include panel-color; height:40px; position:fixed; @@ -178,23 +177,23 @@ table.round-borders { color:white; } - &.current { + &.current { border-bottom: 3px solid #EAEAEA !important; padding: 10px 20px 0; color: #eaeaea; } } - .search-holder { + .search-holder { float:left; - width:290px; + width:290px; input { @include round-borders-all(4px); - width:290px; + width:290px; border-color:#888; padding:5px; background:#666; color:#222; - &:focus { + &:focus { background:#fff; color:#000; } @@ -211,7 +210,7 @@ table.round-borders { padding:20px; } -body { +body { background: #eaeaea; } @@ -220,7 +219,7 @@ a { } .diff_file_content{ - .old_line, .new_line { + .old_line, .new_line { background:#ECECEC; color:#777; width:15px; @@ -230,9 +229,8 @@ a { } } - .view_file_content{ - .old_line, .new_line { + .old_line, .new_line { background:#ECECEC; color:#777; width:15px; @@ -249,20 +247,20 @@ a { border:1px solid #CCC; margin-bottom:1em; - .view_file_header { + .view_file_header { padding:5px 5px; border-bottom:1px solid #CCC; background: #eee; } - .view_file_content { + .view_file_content { background:#fff; color:#514721; font-size: 11px; } - .view_file_content_image { + .view_file_content_image { background:#eee; text-align:center; - img { + img { padding:100px; max-width:300px; } @@ -273,7 +271,7 @@ a { } -input.ssh_project_url { +input.ssh_project_url { padding:5px; margin:0px; float:right; @@ -281,12 +279,10 @@ input.ssh_project_url { text-align:center; } - - -.day-commits-table li.commit { +.day-commits-table li.commit { cursor:pointer; - &:hover { + &:hover { @include hover-color; } } @@ -295,39 +291,39 @@ input.ssh_project_url { #FFF6BF #FFD324 */ -#tree-slider tr.tree-item { +#tree-slider tr.tree-item { cursor:pointer; - &:hover { + &:hover { @include hover-color; - td { + td { @include hover-color; } } } -#projects-list .project { +#projects-list .project { height:50px; } #projects-list .project, #snippets-table .snippet, -#issues-table .issue{ +#issues-table .issue{ cursor:pointer; - &:hover { + &:hover { @include hover-color; - td { + td { @include hover-color; } } } -.clear { +.clear { clear: both; } -.top_project_menu { - a { +.top_project_menu { + a { border-right: 1px solid #FFFFFF; box-shadow: -1px 0 #DDDDDD inset; color: #666; @@ -339,7 +335,7 @@ input.ssh_project_url { text-shadow: 0 1px 0 #FFFFFF; float:left; - &.current { + &.current { background-color: #FFFFFF; color: #222222; } @@ -363,11 +359,11 @@ input.ssh_project_url { .new_project, .new_snippet, .edit_snippet, -.edit_project { +.edit_project { input[type='text'], input[type='email'], input[type='password'], - textarea { + textarea { width:400px; padding:8px; font-size:14px; @@ -375,7 +371,7 @@ input.ssh_project_url { } } -.input_button { +.input_button { //@include round-borders-all(4px); padding:8px; font-size:14px; @@ -393,7 +389,7 @@ tbody tr:nth-child(2n) td, tbody tr.even td { border-bottom: 1px solid #E2EAEE; } -.top_menu_count { +.top_menu_count { background: none repeat scroll 0 0 #FFF6BF; border-color: #FFD324; color: #514721; @@ -417,7 +413,7 @@ tbody tr:nth-child(2n) td, tbody tr.even td { /** FALSH **/ -#flash_container { +#flash_container { height:40px; position:fixed; z-index:1009; @@ -429,7 +425,7 @@ tbody tr:nth-child(2n) td, tbody tr.even td { cursor:pointer; border-bottom:1px solid #777; - h4 { + h4 { color:#444; font-size:22px; padding-top:5px; @@ -460,50 +456,50 @@ tbody tr:nth-child(2n) td, tbody tr.even td { color: #0099FF; } - &.hm { + &.hm { margin: 0px 0px; } - &.vm { + &.vm { margin: 5px 0px; } } /** Notes **/ -#notes-list { +#notes-list { display:block; list-style:none; margin:0px; padding:0px; - li { + li { display:list-item; padding:8px; margin:0px; background: #F7FBFC; border-top: 1px solid #E2EAEE; - &:first-child { + &:first-child { border-top: none; } &:nth-child(2n+1) { background: white; } - p { + p { margin-bottom: 4px; font-size: 13px; color:#111; } } - cite { - &.ago { + cite { + &.ago { color:#666; } } } -.notes_count { +.notes_count { background: none repeat scroll 0 0 #FFF6BF; border-color: #FFD324; color: #514721; @@ -515,36 +511,36 @@ tbody tr:nth-child(2n) td, tbody tr.even td { right: 6px; top: 6px; } -.note_author { +.note_author { float:left; width:60px; } -.note_content { +.note_content { float:left; width:650px; } -.issue_notes { - .note_content { +.issue_notes { + .note_content { float:left; width:400px; } } #user_projects_limit{ - width: 60px; + width: 60px; } -.project_thumb { +.project_thumb { margin:20px 0; width: 250px; float:left; padding:20px; text-align:center; - p, h4 { + p, h4 { text-align:left; } - .lbutton { + .lbutton { float:left; } } @@ -559,8 +555,8 @@ tbody tr:nth-child(2n) td, tbody tr.even td { padding: 10px; } -.recent_message_parent { - img { +.recent_message_parent { + img { padding-right:10px; } @@ -571,7 +567,7 @@ tbody tr:nth-child(2n) td, tbody tr.even td { &.dash_wall{ border-bottom: 2px solid orange; - span { + span { background: orange; color:black; } @@ -579,14 +575,14 @@ tbody tr:nth-child(2n) td, tbody tr.even td { &.dash_issue{ border-bottom: 2px solid #ffbbbb; - span { + span { background: #ffbbbb; } } &.dash_commit{ border-bottom: 2px solid #bbbbff; - span{ + span{ background: #bbbbff; } } @@ -594,27 +590,26 @@ tbody tr:nth-child(2n) td, tbody tr.even td { &.dash_snippet{ border-bottom: 2px solid #bbffbb; - span{ + span{ background: #bbffbb; } } - - span{ + span{ border: 1px solid #aaa; color:black; padding:1px 4px; } - h4 { + h4 { margin-bottom:3px; } } .commit, -.message, +.message, #notes-list{ - .author { + .author { background: #eaeaea; color: #333; border: 1px solid #aaa; @@ -624,17 +619,17 @@ tbody tr:nth-child(2n) td, tbody tr.even td { } /* Note textare */ -#note_note { +#note_note { height:100px; width:97%; font-size:14px; } -.wall_page { - #note_note { +.wall_page { + #note_note { height:25px; } - .attach_holder { + .attach_holder { display:none; } } @@ -653,17 +648,17 @@ tbody tr:nth-child(2n) td, tbody tr.even td { padding:2px 4px; border:none; - &.high { + &.high { background: #D12F19; color:white; } - &.today { + &.today { background: #44aa22; color:white; } - &.yours { + &.yours { background: #4466cc; color:white; } @@ -673,8 +668,8 @@ tbody tr:nth-child(2n) td, tbody tr.even td { } } -#issues-table .issue { - &.critical { +#issues-table .issue { + &.critical { td { //background: #D12F19; //color:#fff; diff --git a/app/controllers/admin/mailer_controller.rb b/app/controllers/admin/mailer_controller.rb index 05ad267f..d2fbbcd4 100644 --- a/app/controllers/admin/mailer_controller.rb +++ b/app/controllers/admin/mailer_controller.rb @@ -20,7 +20,7 @@ class Admin::MailerController < ApplicationController else render :file => 'notify/note_wall_email.html.haml', :layout => 'notify' end - rescue + rescue render :text => "Preview not avaialble" end @@ -29,7 +29,7 @@ class Admin::MailerController < ApplicationController @password = "DHasJKDHAS!" render :file => 'notify/new_user_email.html.haml', :layout => 'notify' - rescue + rescue render :text => "Preview not avaialble" end @@ -38,7 +38,7 @@ class Admin::MailerController < ApplicationController @user = @issue.assignee @project = @issue.project render :file => 'notify/new_issue_email.html.haml', :layout => 'notify' - rescue + rescue render :text => "Preview not avaialble" end end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index e9ad1e55..f60330f7 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -36,7 +36,7 @@ class Admin::UsersController < ApplicationController def create admin = params[:user].delete("admin") - @admin_user = User.new(params[:user]) + @admin_user = User.new(params[:user]) @admin_user.admin = (admin && admin.to_i > 0) respond_to do |format| @@ -54,8 +54,8 @@ class Admin::UsersController < ApplicationController def update admin = params[:user].delete("admin") if params[:user][:password].empty? - params[:user].delete(:password) - params[:user].delete(:password_confirmation) + params[:user].delete(:password) + params[:user].delete(:password_confirmation) end @admin_user = User.find(params[:id]) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 047c6cb7..816c4c55 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -8,7 +8,7 @@ class ApplicationController < ActionController::Base render :file => File.join(Rails.root, "public", "gitosis_error"), :layout => false end - protected + protected def abilities @abilities ||= Six.new @@ -18,7 +18,7 @@ class ApplicationController < ActionController::Base abilities.allowed?(object, action, subject) end - def project + def project @project ||= Project.find_by_code(params[:project_id]) end @@ -55,7 +55,7 @@ class ApplicationController < ActionController::Base @tag = unless params[:tag].blank? params[:tag] - else + else nil end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 757ada94..56d711db 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -1,12 +1,12 @@ class IssuesController < ApplicationController before_filter :authenticate_user! - before_filter :project + before_filter :project before_filter :issue, :only => [:edit, :update, :destroy, :show] # Authorize before_filter :add_project_abilities before_filter :authorize_read_issue! - before_filter :authorize_write_issue!, :only => [:new, :create, :close, :edit, :update, :sort] + before_filter :authorize_write_issue!, :only => [:new, :create, :close, :edit, :update, :sort] respond_to :js @@ -57,14 +57,13 @@ class IssuesController < ApplicationController end end - def destroy return access_denied! unless can?(current_user, :admin_issue, @issue) @issue.destroy respond_to do |format| - format.js { render :nothing => true } + format.js { render :nothing => true } end end @@ -78,7 +77,7 @@ class IssuesController < ApplicationController render :nothing => true end - protected + protected def issue @issue ||= @project.issues.find(params[:id]) diff --git a/app/controllers/keys_controller.rb b/app/controllers/keys_controller.rb index b0249375..d3c93b5f 100644 --- a/app/controllers/keys_controller.rb +++ b/app/controllers/keys_controller.rb @@ -24,7 +24,7 @@ class KeysController < ApplicationController respond_to do |format| format.html { redirect_to keys_url } - format.js { render :nothing => true } + format.js { render :nothing => true } end end end diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 46425664..ad9531e0 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -1,9 +1,9 @@ class NotesController < ApplicationController - before_filter :project + before_filter :project # Authorize before_filter :add_project_abilities - before_filter :authorize_write_note!, :only => [:create] + before_filter :authorize_write_note!, :only => [:create] respond_to :js @@ -15,10 +15,9 @@ class NotesController < ApplicationController notify if params[:notify] == '1' end - respond_to do |format| format.html {redirect_to :back} - format.js + format.js end end @@ -30,11 +29,11 @@ class NotesController < ApplicationController @note.destroy respond_to do |format| - format.js { render :nothing => true } + format.js { render :nothing => true } end end - protected + protected def notify @project.users.reject { |u| u.id == current_user.id } .each do |u| diff --git a/app/controllers/profile_controller.rb b/app/controllers/profile_controller.rb index c8477729..a0078f0e 100644 --- a/app/controllers/profile_controller.rb +++ b/app/controllers/profile_controller.rb @@ -14,7 +14,7 @@ class ProfileController < ApplicationController end def password_update - params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"} + params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"} @user = current_user if @user.update_attributes(params[:user]) diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 54d19af7..481e02fd 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -1,10 +1,10 @@ class ProjectsController < ApplicationController - before_filter :project, :except => [:index, :new, :create] + before_filter :project, :except => [:index, :new, :create] # Authorize before_filter :add_project_abilities - before_filter :authorize_read_project!, :except => [:index, :new, :create] - before_filter :authorize_admin_project!, :only => [:edit, :update, :destroy] + before_filter :authorize_read_project!, :except => [:index, :new, :create] + before_filter :authorize_admin_project!, :only => [:edit, :update, :destroy] before_filter :require_non_empty_project, :only => [:blob, :tree] @@ -23,7 +23,7 @@ class ProjectsController < ApplicationController @project = Project.new(params[:project]) @project.owner = current_user - Project.transaction do + Project.transaction do @project.save! @project.users_projects.create!(:admin => true, :read => true, :write => true, :user => current_user) end @@ -31,7 +31,7 @@ class ProjectsController < ApplicationController respond_to do |format| if @project.valid? format.html { redirect_to @project, notice: 'Project was successfully created.' } - format.js + format.js else format.html { render action: "new" } format.js @@ -51,10 +51,10 @@ class ProjectsController < ApplicationController respond_to do |format| if project.update_attributes(params[:project]) format.html { redirect_to project, :notice => 'Project was successfully updated.' } - format.js + format.js else format.html { render action: "edit" } - format.js + format.js end end end @@ -105,7 +105,7 @@ class ProjectsController < ApplicationController if params[:commit_id] @commit = @repo.commits(params[:commit_id]).first - else + else @commit = @repo.commits(@ref || "master").first end @@ -114,7 +114,7 @@ class ProjectsController < ApplicationController respond_to do |format| format.html # show.html.erb - format.js do + format.js do # diasbale cache to allow back button works response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" response.headers["Pragma"] = "no-cache" @@ -132,7 +132,7 @@ class ProjectsController < ApplicationController if @tree.is_a?(Grit::Blob) send_data(@tree.data, :type => @tree.mime_type, :disposition => 'inline', :filename => @tree.name) - else + else head(404) end rescue @@ -147,9 +147,9 @@ class ProjectsController < ApplicationController end end - protected + protected - def project + def project @project ||= Project.find_by_code(params[:id]) end end diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index b31fe683..d9a6ab2a 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -1,11 +1,11 @@ class SnippetsController < ApplicationController before_filter :authenticate_user! - before_filter :project + before_filter :project # Authorize before_filter :add_project_abilities before_filter :authorize_read_snippet! - before_filter :authorize_write_snippet!, :only => [:new, :create, :close, :edit, :update, :sort] + before_filter :authorize_write_snippet!, :only => [:new, :create, :close, :edit, :update, :sort] respond_to :html @@ -13,7 +13,7 @@ class SnippetsController < ApplicationController @snippets = @project.snippets end - def new + def new @snippet = @project.snippets.new end diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb index 84addf8d..48e7e9b9 100644 --- a/app/controllers/team_members_controller.rb +++ b/app/controllers/team_members_controller.rb @@ -1,10 +1,10 @@ class TeamMembersController < ApplicationController - before_filter :project + before_filter :project # Authorize before_filter :add_project_abilities before_filter :authorize_read_project! - before_filter :authorize_admin_project!, :only => [:new, :create, :destroy, :update] + before_filter :authorize_admin_project!, :only => [:new, :create, :destroy, :update] def show @team_member = project.users_projects.find(params[:id]) @@ -26,7 +26,7 @@ class TeamMembersController < ApplicationController respond_to do |format| format.js - format.html do + format.html do unless @team_member.valid? flash[:alert] = "User should have at least one role" end @@ -41,7 +41,7 @@ class TeamMembersController < ApplicationController respond_to do |format| format.html { redirect_to root_path } - format.js { render :nothing => true } + format.js { render :nothing => true } end end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 0895eb0d..599d1e5c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -23,9 +23,9 @@ module ApplicationHelper end def last_commit(project) - if project.repo_exists? + if project.repo_exists? time_ago_in_words(project.commit.committed_date) + " ago" - else + else "Never" end end @@ -33,8 +33,8 @@ module ApplicationHelper def search_autocomplete_source projects = current_user.projects.map{ |p| { :label => p.name, :url => project_path(p) } } default_nav = [ - { :label => "Keys", :url => keys_path }, - { :label => "Projects", :url => projects_path }, + { :label => "Keys", :url => keys_path }, + { :label => "Projects", :url => projects_path }, { :label => "Admin", :url => admin_root_path } ] @@ -42,10 +42,10 @@ module ApplicationHelper if @project && !@project.new_record? project_nav = [ - { :label => "#{@project.code} / Issues", :url => project_issues_path(@project) }, - { :label => "#{@project.code} / Wall", :url => wall_project_path(@project) }, - { :label => "#{@project.code} / Tree", :url => tree_project_path(@project) }, - { :label => "#{@project.code} / Commits", :url => project_commits_path(@project) }, + { :label => "#{@project.code} / Issues", :url => project_issues_path(@project) }, + { :label => "#{@project.code} / Wall", :url => wall_project_path(@project) }, + { :label => "#{@project.code} / Tree", :url => tree_project_path(@project) }, + { :label => "#{@project.code} / Commits", :url => project_commits_path(@project) }, { :label => "#{@project.code} / Team", :url => team_project_path(@project) } ] end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index f1b54668..bc95f916 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -1,13 +1,13 @@ module CommitsHelper def diff_line(line, line_new = 0, line_old = 0) full_line = html_escape(line.gsub(/\n/, '')) - color = if line[0] == "+" + color = if line[0] == "+" full_line = " #{line_new} " + full_line "#DFD" - elsif line[0] == "-" + elsif line[0] == "-" full_line = "#{line_old}  " + full_line "#FDD" - else + else full_line = "#{line_old}#{line_new} " + full_line "none" end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 4a6923af..75ab737c 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -12,7 +12,7 @@ module ProjectsHelper else true end - rescue + rescue nil end end diff --git a/app/models/ability.rb b/app/models/ability.rb index b822f630..5ab70650 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -17,14 +17,14 @@ class Ability :read_issue, :read_snippet, :read_team_member, - :read_note + :read_note ] if project.readers.include?(user) rules << [ :write_project, :write_issue, :write_snippet, - :write_note + :write_note ] if project.writers.include?(user) rules << [ @@ -32,13 +32,13 @@ class Ability :admin_issue, :admin_snippet, :admin_team_member, - :admin_note + :admin_note ] if project.admins.include?(user) rules.flatten end - class << self + class << self [:issue, :note, :snippet].each do |name| define_method "#{name}_abilities" do |user, subject| if subject.author == user @@ -48,7 +48,7 @@ class Ability :"admin_#{name}" ] else - subject.respond_to?(:project) ? + subject.respond_to?(:project) ? project_abilities(user, subject.project) : [] end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 904965ac..ca1c5eaf 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -13,7 +13,7 @@ class Issue < ActiveRecord::Base validates :title, :presence => true, :length => { :within => 0..255 } - + validates :content, :presence => true, :length => { :within => 0..2000 } @@ -30,7 +30,7 @@ class Issue < ActiveRecord::Base def today? Date.today == created_at.to_date end - + def new? today? && created_at == updated_at end diff --git a/app/models/key.rb b/app/models/key.rb index 29dcbbce..1559b5bd 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -17,11 +17,11 @@ class Key < ActiveRecord::Base def set_identifier self.identifier = "#{user.identifier}_#{Time.now.to_i}" end - + def update_gitosis Gitosis.new.configure do |c| c.update_keys(identifier, key) - + projects.each do |project| c.update_project(project.path, project.gitosis_writers) end diff --git a/app/models/note.rb b/app/models/note.rb index e3dabce4..9dcdbb55 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -7,7 +7,7 @@ class Note < ActiveRecord::Base belongs_to :author, :class_name => "User" - attr_protected :author, :author_id + attr_protected :author, :author_id validates_presence_of :project @@ -15,10 +15,10 @@ class Note < ActiveRecord::Base :presence => true, :length => { :within => 0..255 } - validates :attachment, - :file_size => { - :maximum => 10.megabytes.to_i - } + validates :attachment, + :file_size => { + :maximum => 10.megabytes.to_i + } scope :common, where(:noteable_id => nil) diff --git a/app/models/project.rb b/app/models/project.rb index 5262e552..ef7f4e46 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -20,7 +20,7 @@ class Project < ActiveRecord::Base :format => { :with => /^[a-zA-Z0-9_\-]*$/, :message => "only letters, digits & '_' '-' allowed" }, :length => { :within => 0..255 } - + validates :description, :length => { :within => 0..2000 } @@ -57,13 +57,13 @@ class Project < ActiveRecord::Base c.update_project(path, gitosis_writers) end end - + def destroy_gitosis_project Gitosis.new.configure do |c| c.destroy_project(self) end end - + def add_access(user, *access) opts = { :user => user } access.each { |name| opts.merge!(name => true) } @@ -102,12 +102,12 @@ class Project < ActiveRecord::Base def url_to_repo "#{GITOSIS["git_user"]}@#{GITOSIS["host"]}:#{path}.git" end - + def path_to_repo GITOSIS["base_path"] + path + ".git" end - def repo + def repo @repo ||= Grit::Repo.new(path_to_repo) end @@ -122,17 +122,17 @@ class Project < ActiveRecord::Base def commit(commit_id = nil) if commit_id repo.commits(commit_id).first - else + else repo.commits.first end end - def heads + def heads @heads ||= repo.heads end def fresh_commits - commits = heads.map do |h| + commits = heads.map do |h| repo.commits(h.name, 10) end.flatten.uniq { |c| c.id } @@ -144,7 +144,7 @@ class Project < ActiveRecord::Base end def commits_since(date) - commits = heads.map do |h| + commits = heads.map do |h| repo.log(h.name, nil, :since => date) end.flatten.uniq { |c| c.id } @@ -165,7 +165,7 @@ class Project < ActiveRecord::Base unless owner.can_create_project? errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it") end - rescue + rescue errors[:base] << ("Cant check your ability to create project") end diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 95d6a07d..0f488a8c 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -13,7 +13,7 @@ class Snippet < ActiveRecord::Base validates :title, :presence => true, :length => { :within => 0..255 } - + validates :file_name, :presence => true, :length => { :within => 0..255 } @@ -22,9 +22,8 @@ class Snippet < ActiveRecord::Base :presence => true, :length => { :within => 0..10000 } - def self.content_types - [ + [ ".rb", ".py", ".pl", ".scala", ".c", ".cpp", ".java", ".haml", ".html", ".sass", ".scss", ".xml", ".php", ".erb", ".js", ".sh", ".coffee", ".yml", ".md" diff --git a/app/models/user.rb b/app/models/user.rb index 7736599e..c90cf49f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,7 +5,7 @@ class User < ActiveRecord::Base :recoverable, :rememberable, :trackable, :validatable # Setup accessible (or protected) attributes for your model - attr_accessible :email, :password, :password_confirmation, :remember_me, + attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :projects_limit, :skype, :linkedin, :twitter has_many :users_projects, :dependent => :destroy diff --git a/app/views/admin/mailer/preview.html.haml b/app/views/admin/mailer/preview.html.haml index 7b723cb8..60e24588 100644 --- a/app/views/admin/mailer/preview.html.haml +++ b/app/views/admin/mailer/preview.html.haml @@ -1,29 +1,28 @@ %p This is page with preview for all system emails that are sent to user -%p Email previews built based on existing Project/Commit/Issue base - so some preview maybe unavailable unless object appear in system +%p Email previews built based on existing Project/Commit/Issue base - so some preview maybe unavailable unless object appear in system #accordion %h3 %a New user - %div + %div %iframe{ :src=> admin_mailer_preview_user_new_path, :width=>"100%", :height=>"350"} %h3 %a New issue - %div + %div %iframe{ :src=> admin_mailer_preview_issue_new_path, :width=>"100%", :height=>"350"} - %h3 + %h3 %a Commit note %div %iframe{ :src=> admin_mailer_preview_note_path(:type => "Commit"), :width=>"100%", :height=>"350"} %h3 %a Issue note - %div + %div %iframe{ :src=> admin_mailer_preview_note_path(:type => "Issue"), :width=>"100%", :height=>"350"} %h3 %a Wall note - %div + %div %iframe{ :src=> admin_mailer_preview_note_path(:type => "Wall"), :width=>"100%", :height=>"350"} - -:javascript +:javascript $(function() { $( "#accordion" ).accordion(); }); diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 68918941..fc2e6324 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -1,7 +1,7 @@ %p#notice= notice .span-8.colborder - %h2= @admin_project.name + %h2= @admin_project.name %p %b Name: @@ -22,16 +22,16 @@ .span-14 - %h2 Team + %h2 Team %table.round-borders %tr %th Name - %th Added + %th Added %th Web %th Git %th Admin - %th + %th - @admin_project.users_projects.each do |tm| %tr diff --git a/app/views/admin/team_members/index.html.haml b/app/views/admin/team_members/index.html.haml index bbd7a6c0..5aa4b597 100644 --- a/app/views/admin/team_members/index.html.haml +++ b/app/views/admin/team_members/index.html.haml @@ -7,8 +7,8 @@ %th Read %th Git %th Manage - %th Added - %th + %th Added + %th %th %th - members.each do |tm| diff --git a/app/views/admin/team_members/show.html.haml b/app/views/admin/team_members/show.html.haml index bd30c7b0..29d1160c 100644 --- a/app/views/admin/team_members/show.html.haml +++ b/app/views/admin/team_members/show.html.haml @@ -11,7 +11,6 @@ %b Since: = @admin_team_member.updated_at - .span-10 .span-6 %b Access: diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index aa9df298..51b5d5c7 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -44,7 +44,7 @@ .field = f.label :twitter %br - = f.text_field :twitter + = f.text_field :twitter .clear %br .actions diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml index cec6e3e1..b188d2ab 100644 --- a/app/views/admin/users/new.html.haml +++ b/app/views/admin/users/new.html.haml @@ -2,5 +2,4 @@ = render 'form' - = link_to 'Back', admin_users_path, :class => "right lbutton" diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index aee73c38..5bc5bf9a 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -19,28 +19,27 @@ = @admin_user.skype %p %b LinkedIn: - = @admin_user.linkedin + = @admin_user.linkedin %p %b Twitter: = @admin_user.twitter - .clear = link_to 'Edit', edit_admin_user_path(@admin_user) \| = link_to 'Back', admin_users_path .span-14 - %h2 Projects + %h2 Projects %table.round-borders %tr %th Name - %th Added + %th Added %th Web %th Git %th Admin - %th + %th - @admin_user.users_projects.each do |tm| - project = tm.project diff --git a/app/views/commits/_diff.html.haml b/app/views/commits/_diff.html.haml index 2807e090..e385d9dd 100644 --- a/app/views/commits/_diff.html.haml +++ b/app/views/commits/_diff.html.haml @@ -8,7 +8,7 @@ .diff_file_header - if diff.deleted_file %strong{:id => "#{diff.b_path}"}= diff.a_path - - else + - else = link_to tree_file_project_path(@project, @commit.id, diff.b_path) do %strong{:id => "#{diff.b_path}"}= diff.b_path %br/ @@ -19,5 +19,5 @@ .diff_file_content_image %img{:src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} - else - %p + %p %center No preview for this file type diff --git a/app/views/commits/_index.html.haml b/app/views/commits/_index.html.haml index e4c9cc6e..f1e4c7eb 100644 --- a/app/views/commits/_index.html.haml +++ b/app/views/commits/_index.html.haml @@ -6,4 +6,4 @@ %h1 Listing commits %div{:id => dom_id(@project)} = render "commits" -%br/ \ No newline at end of file +%br/ diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml index 67033ade..db71c387 100644 --- a/app/views/commits/_text_file.html.haml +++ b/app/views/commits/_text_file.html.haml @@ -12,10 +12,10 @@ = diff_line(line, line_new, line_old) - if line[0] == "+" - line_new += 1 - - elsif + - elsif - line[0] == "-" - line_old += 1 - - else + - else - line_new += 1 - line_old += 1 diff --git a/app/views/commits/show.js.haml b/app/views/commits/show.js.haml index cec1fe28..9831bb29 100644 --- a/app/views/commits/show.js.haml +++ b/app/views/commits/show.js.haml @@ -4,5 +4,5 @@ side.html("#{escape_javascript(render "commits/show")}"); $("##{dom_id(@project)}").parent().append(side); $("##{dom_id(@project)}").addClass("span-14"); -:plain +:plain $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb index b7ae403c..5399a961 100644 --- a/app/views/devise/confirmations/new.html.erb +++ b/app/views/devise/confirmations/new.html.erb @@ -9,4 +9,4 @@
          <%= f.submit "Resend confirmation instructions" %>
          <% end %> -<%= render :partial => "devise/shared/links" %> \ No newline at end of file +<%= render :partial => "devise/shared/links" %> diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb index e75c9371..ff76588c 100644 --- a/app/views/devise/passwords/edit.html.erb +++ b/app/views/devise/passwords/edit.html.erb @@ -13,4 +13,4 @@
          <%= f.submit "Change my password" %>
          <% end %> -<%= render :partial => "devise/shared/links" %> \ No newline at end of file +<%= render :partial => "devise/shared/links" %> diff --git a/app/views/devise/shared/_links.erb b/app/views/devise/shared/_links.erb index eab783a4..33b1120f 100644 --- a/app/views/devise/shared/_links.erb +++ b/app/views/devise/shared/_links.erb @@ -22,4 +22,4 @@ <%- resource_class.omniauth_providers.each do |provider| %> <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %>
          <% end -%> -<% end -%> \ No newline at end of file +<% end -%> diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb index c6cdcfe5..b787e648 100644 --- a/app/views/devise/unlocks/new.html.erb +++ b/app/views/devise/unlocks/new.html.erb @@ -9,4 +9,4 @@
          <%= f.submit "Resend unlock instructions" %>
          <% end %> -<%= render :partial => "devise/shared/links" %> \ No newline at end of file +<%= render :partial => "devise/shared/links" %> diff --git a/app/views/issues/_issues.html.haml b/app/views/issues/_issues.html.haml index 42e8371a..11e4c38e 100644 --- a/app/views/issues/_issues.html.haml +++ b/app/views/issues/_issues.html.haml @@ -1,7 +1,7 @@ %table.round-borders#issues-table %tr - if can?(current_user, :admin_issue, @project) && !params[:f] || params[:f] == "0" - %th + %th %th Assignee %th ID %th Title diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml index fcac006e..afcd2b6e 100644 --- a/app/views/issues/_show.html.haml +++ b/app/views/issues/_show.html.haml @@ -21,10 +21,10 @@ -#notes %td - if can? current_user, :write_issue, @project - = form_for([@project, issue], :remote => true) do |f| + = form_for([@project, issue], :remote => true) do |f| = f.check_box :closed, :onclick => "$(this).parent().submit();" = hidden_field_tag :status_only, true - - else + - else = check_box_tag "closed", 1, issue.closed, :disabled => true %td - if can?(current_user, :admin_issue, @project) || issue.author == current_user diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml index 6f4548a8..46a15ef1 100644 --- a/app/views/issues/index.html.haml +++ b/app/views/issues/index.html.haml @@ -12,7 +12,7 @@ .span-2 = radio_button_tag :f, 3, params[:f] == "3", :onclick => "this.form.submit()", :id => "my_issues" = label_tag "my_issues","To Me" - + .span-2 = radio_button_tag :f, 1, params[:f] == "1", :onclick => "this.form.submit()", :id => "all_issues" = label_tag "all_issues","All" @@ -20,9 +20,9 @@ #issues-table-holder= render "issues" %br :javascript - $('.delete-issue').live('ajax:success', function() { - $(this).closest('tr').fadeOut(); }); - + $('.delete-issue').live('ajax:success', function() { + $(this).closest('tr').fadeOut(); }); + function setSortable(){ $('#issues-table>tbody').sortable({ axis: 'y', diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 199c80c8..29b6f3f7 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -8,24 +8,24 @@ .span-8 - if @issue.closed %center.success Closed - - else + - else %center.error Open %table.round-borders %tr - %td Title: + %td Title: %td = truncate html_escape(@issue.title) %tr - %td Project + %td Project %td %strong= @issue.project.name %tr - %td Author: + %td Author: %td = image_tag gravatar_icon(@issue.author.email), :class => "left", :width => 40, :style => "padding:0 5px;" = @issue.author.name %tr - %td Assignee: + %td Assignee: %td = image_tag gravatar_icon(@issue.assignee.email), :class => "left", :width => 40, :style => "padding:0 5px;" = @issue.assignee.name @@ -33,12 +33,11 @@ %td Closed? %td - if can? current_user, :write_issue, @project - = form_for([@project, @issue]) do |f| + = form_for([@project, @issue]) do |f| = f.check_box :closed, :onclick => "$(this).parent().submit();" = hidden_field_tag :status_only, true - - else + - else = check_box_tag "closed", 1, @issue.closed, :disabled => true - .clear diff --git a/app/views/issues/show.js.haml b/app/views/issues/show.js.haml index 5b9a34c0..ae2ff32c 100644 --- a/app/views/issues/show.js.haml +++ b/app/views/issues/show.js.haml @@ -1,2 +1,2 @@ -:plain +:plain $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); diff --git a/app/views/issues/update.js.haml b/app/views/issues/update.js.haml index c365c3f5..30fca38c 100644 --- a/app/views/issues/update.js.haml +++ b/app/views/issues/update.js.haml @@ -2,7 +2,7 @@ - if @issue.valid? :plain $("##{dom_id(@issue)}").fadeOut(); -- else +- else - if @issue.valid? :plain $("#edit_issue_dialog").dialog("close"); diff --git a/app/views/keys/index.html.haml b/app/views/keys/index.html.haml index 416ae8f8..279b125f 100644 --- a/app/views/keys/index.html.haml +++ b/app/views/keys/index.html.haml @@ -10,6 +10,6 @@ = render(:partial => 'show', :locals => {:key => key}) :javascript - $('.delete-key').live('ajax:success', function() { - $(this).closest('tr').fadeOut(); }); + $('.delete-key').live('ajax:success', function() { + $(this).closest('tr').fadeOut(); }); diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml index 4b6eb2b5..4011485c 100644 --- a/app/views/layouts/_flash.html.haml +++ b/app/views/layouts/_flash.html.haml @@ -6,9 +6,9 @@ %h4= text :javascript $(function(){ - $("#flash_container").slideDown("slow"); - $("#flash_container").click(function(){ - $(this).slideUp("slow"); + $("#flash_container").slideDown("slow"); + $("#flash_container").click(function(){ + $(this).slideUp("slow"); }); setTimeout("hideFlash()",2000); }); diff --git a/app/views/layouts/_head_panel.html.erb b/app/views/layouts/_head_panel.html.erb index 047f708b..07de8de4 100644 --- a/app/views/layouts/_head_panel.html.erb +++ b/app/views/layouts/_head_panel.html.erb @@ -22,7 +22,6 @@
      - <% if current_user %> <%= javascript_tag do %> $(function() { diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index ca56a245..14e74fa6 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -22,7 +22,7 @@ = check_box_tag :notify, 1, true = label_tag :notify, "Notify project team about your note" - + .clear %br = f.submit 'Add note', :class => "lbutton vm", :id => "submit_note" diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml index 2d110162..e7cc2360 100644 --- a/app/views/notes/_notes.html.haml +++ b/app/views/notes/_notes.html.haml @@ -1,7 +1,7 @@ - if controller.action_name == "wall" %ul#notes-list= render "notes/notes_list" -- else +- else %ul#notes-list= render "notes/notes_list" %br %br @@ -9,17 +9,16 @@ = render "notes/form" :javascript - $('.delete-note').live('ajax:success', function() { - $(this).closest('li').fadeOut(); }); + $('.delete-note').live('ajax:success', function() { + $(this).closest('li').fadeOut(); }); $("#new_note").live("ajax:before", function(){ - $("#submit_note").attr("disabled", "disabled"); + $("#submit_note").attr("disabled", "disabled"); }) $("#new_note").live("ajax:complete", function(){ - $("#submit_note").removeAttr("disabled"); + $("#submit_note").removeAttr("disabled"); }) - - if ["issues", "projects"].include?(controller.controller_name) :javascript diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index 15371dbc..a04130e8 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -7,5 +7,5 @@ :plain $("#new_note").replaceWith("#{escape_javascript(render('form'))}"); -:plain +:plain $("#submit_note").removeAttr("disabled"); diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml index 213a7379..1a5a603a 100644 --- a/app/views/notify/new_issue_email.html.haml +++ b/app/views/notify/new_issue_email.html.haml @@ -10,9 +10,9 @@ %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} %td{:align => "left", :style => "padding: 20px 0 0;"} %h2{:style => "color:#646464 !important; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "} - = link_to project_issue_url(@project, @issue) do + = link_to project_issue_url(@project, @issue) do = "Issue ##{@issue.id.to_s}" - = truncate(@issue.title, :length => 45) + = truncate(@issue.title, :length => 45) %br %cite{:style => "color:#767676; font-weight: normal; margin: 0; padding: 0; line-height: 20px; font-size: 12px;font-family: Helvetica, Arial, sans-serif; "} = @issue.content diff --git a/app/views/notify/new_user_email.html.haml b/app/views/notify/new_user_email.html.haml index 969ea7e5..2d3abf2e 100644 --- a/app/views/notify/new_user_email.html.haml +++ b/app/views/notify/new_user_email.html.haml @@ -4,7 +4,7 @@ %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} %td{:align => "left", :style => "padding: 20px 0 0;"} %h2{:style => "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "} - Hi #{@user.name}! + Hi #{@user.name}! %p{:style => "color:#767676; font-weight: normal; margin: 0; padding: 0; line-height: 20px; font-size: 12px;font-family: Helvetica, Arial, sans-serif; "} Administrator created account for you. Now you are a member of company gitlab application. %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} diff --git a/app/views/notify/note_issue_email.html.haml b/app/views/notify/note_issue_email.html.haml index 242c97bf..7d8e2156 100644 --- a/app/views/notify/note_issue_email.html.haml +++ b/app/views/notify/note_issue_email.html.haml @@ -4,10 +4,10 @@ %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} %td{:align => "left", :style => "padding: 20px 0 0;"} %h2{:style => "color:#646464 !important; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "} - New comment - - = link_to project_issue_url(@project, @issue, :anchor => "note_#{@note.id}") do + New comment - + = link_to project_issue_url(@project, @issue, :anchor => "note_#{@note.id}") do = "Issue ##{@issue.id.to_s}" - = truncate(@issue.title, :length => 35) + = truncate(@issue.title, :length => 35) %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} %tr %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} diff --git a/app/views/notify/note_wall_email.html.haml b/app/views/notify/note_wall_email.html.haml index c9fdae12..a2bd5a76 100644 --- a/app/views/notify/note_wall_email.html.haml +++ b/app/views/notify/note_wall_email.html.haml @@ -4,7 +4,7 @@ %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} %td{:align => "left", :style => "padding: 20px 0 0;"} %h2{:style => "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "} - New message on + New message on = link_to "Project Wall", wall_project_url(@project, :anchor => "note_#{@note.id}") %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} %tr diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 00ca98ef..164f1d45 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -21,7 +21,7 @@ %td = f.text_field :path, :placeholder => "example_project", :disabled => !@project.new_record? %tr - %td + %td .left= f.label :code %cite.right http://yourserver/ %td= f.text_field :code, :placeholder => "example" @@ -39,10 +39,10 @@ = image_tag "ajax-loader.gif", :class => "append-bottom" - if @project.new_record? %h3.prepend-top Creating project & repository. Please wait for few minutes - - else + - else %h3.prepend-top Updating project & repository. Please wait for few minutes :javascript - $('.new_project, .edit_project').bind('ajax:before', function() { - $(this).find(".form_content").hide(); + $('.new_project, .edit_project').bind('ajax:before', function() { + $(this).find(".form_content").hide(); $('.ajax_loader').show(); - }); + }); diff --git a/app/views/projects/_list.html.haml b/app/views/projects/_list.html.haml index aec61ffb..65f0b7fd 100644 --- a/app/views/projects/_list.html.haml +++ b/app/views/projects/_list.html.haml @@ -16,7 +16,7 @@ %td= check_box_tag "read", 1, project.readers.include?(current_user), :disabled => :disabled %td= check_box_tag "commit", 1, project.writers.include?(current_user), :disabled => :disabled %td= check_box_tag "admin", 1, project.admins.include?(current_user), :disabled => :disabled - %td + %td -if can? current_user, :admin_project, project = link_to 'Edit', edit_project_path(project), :class => "lbutton positive" %br diff --git a/app/views/projects/_projects_top_menu.html.haml b/app/views/projects/_projects_top_menu.html.haml index f80f28a8..9e199183 100644 --- a/app/views/projects/_projects_top_menu.html.haml +++ b/app/views/projects/_projects_top_menu.html.haml @@ -11,7 +11,7 @@ $(".list").toggle(); if($(".tile").is(":visible")){ $.cookie('project_view', 'tile', { expires: 14 }); - } else { + } else { $.cookie('project_view', 'list', { expires: 14 }); } } diff --git a/app/views/projects/_recent_commits.html.haml b/app/views/projects/_recent_commits.html.haml index 3157c356..b34470d6 100644 --- a/app/views/projects/_recent_commits.html.haml +++ b/app/views/projects/_recent_commits.html.haml @@ -6,8 +6,8 @@ = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" %p{:style => "margin-bottom: 3px;"} %strong - = link_to truncate(commit.safe_message, :length => 60), project_commit_path(@project, :id => commit.id) - + = link_to truncate(commit.safe_message, :length => 60), project_commit_path(@project, :id => commit.id) + %span %span.author = commit.author.name.force_encoding("UTF-8") diff --git a/app/views/projects/_team.html.haml b/app/views/projects/_team.html.haml index bb906336..4001c7a2 100644 --- a/app/views/projects/_team.html.haml +++ b/app/views/projects/_team.html.haml @@ -14,5 +14,5 @@ = render(:partial => 'team_members/show', :locals => {:member => up}) :javascript - $('.delete-team-member').live('ajax:success', function() { - $(this).closest('tr').fadeOut(); }); + $('.delete-team-member').live('ajax:success', function() { + $(this).closest('tr').fadeOut(); }); diff --git a/app/views/projects/empty.html.erb b/app/views/projects/empty.html.erb index 4c60facd..ffc1ebfa 100644 --- a/app/views/projects/empty.html.erb +++ b/app/views/projects/empty.html.erb @@ -40,7 +40,7 @@ eos

      Be careful!
      Project cant be recovered after destroy.

      - <%= link_to 'Destroy', @project, + <%= link_to 'Destroy', @project, :confirm => 'Are you sure?', :method => :delete, :class => "left button negative span-6", :style => "text-align:center" %>
      diff --git a/app/views/projects/index.html.haml b/app/views/projects/index.html.haml index 888a72b6..4b9457c1 100644 --- a/app/views/projects/index.html.haml +++ b/app/views/projects/index.html.haml @@ -3,7 +3,7 @@ = render "tile" %div{:class => "list", :style => view_mode_style("list")} = render "list" -- else +- else %center.prepend-top %h2 %cite Nothing here diff --git a/app/views/projects/tree.js.haml b/app/views/projects/tree.js.haml index 60cbd199..eb08adb1 100644 --- a/app/views/projects/tree.js.haml +++ b/app/views/projects/tree.js.haml @@ -1,5 +1,5 @@ :plain - $("#tree-holder table").hide("slide", { direction: "left" }, 150, function(){ + $("#tree-holder table").hide("slide", { direction: "left" }, 150, function(){ $("#tree-holder").html("#{escape_javascript(render(:partial => "tree", :locals => {:repo => @repo, :commit => @commit, :tree => @tree}))}"); $("#tree-holder table").show("slide", { direction: "right" }, 150); }); diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml index ed22478c..63c9613a 100644 --- a/app/views/projects/wall.html.haml +++ b/app/views/projects/wall.html.haml @@ -20,7 +20,7 @@ %hr = render "notes/notes" -:javascript +:javascript $(function(){ $("#note_note").live("click", function(){ $(this).css("height", "100px"); diff --git a/app/views/projects/wall.js.haml b/app/views/projects/wall.js.haml index 5b9a34c0..ae2ff32c 100644 --- a/app/views/projects/wall.js.haml +++ b/app/views/projects/wall.js.haml @@ -1,2 +1,2 @@ -:plain +:plain $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml index 571e2b06..7a34ae8e 100644 --- a/app/views/snippets/_form.html.haml +++ b/app/views/snippets/_form.html.haml @@ -17,6 +17,6 @@ = f.label :content, "Code" %br = f.text_area :content, :style => "height:240px;width:932px;" - + .actions.prepend-top = f.submit 'Save', :class => "lbutton vm" diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml index 6e5dbde5..fe5e6170 100644 --- a/app/views/snippets/index.html.haml +++ b/app/views/snippets/index.html.haml @@ -10,5 +10,5 @@ %th = render @snippets :javascript - $('.delete-snippet').live('ajax:success', function() { - $(this).closest('tr').fadeOut(); }); + $('.delete-snippet').live('ajax:success', function() { + $(this).closest('tr').fadeOut(); }); diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml index b9a68e6c..88260cca 100644 --- a/app/views/team_members/_show.html.haml +++ b/app/views/team_members/_show.html.haml @@ -7,11 +7,11 @@ %td= truncate user.email, :lenght => 16 - if can? current_user, :admin_project, @project - = form_for(member, :as => :team_member, :url => project_team_member_path(@project, member)) do |f| + = form_for(member, :as => :team_member, :url => project_team_member_path(@project, member)) do |f| %td= f.check_box :read, :onclick => "$(this.form).submit();" %td= f.check_box :write, :onclick => "$(this.form).submit();" %td= f.check_box :admin, :onclick => "$(this.form).submit();" - - else + - else %td= check_box_tag "read", 1, member.read, :disabled => :disabled %td= check_box_tag "commit", 1, member.write, :disabled => :disabled %td= check_box_tag "admin", 1, member.admin, :disabled => :disabled diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml index d07c54f8..4a093ee1 100644 --- a/app/views/team_members/show.html.haml +++ b/app/views/team_members/show.html.haml @@ -25,4 +25,3 @@ %b Twitter: = user.twitter - diff --git a/config/environments/production.rb b/config/environments/production.rb index 7ebe4523..d8094817 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -58,7 +58,6 @@ Gitlab::Application.configure do # Send deprecation notices to registered listeners config.active_support.deprecation = :notify - config.action_mailer.delivery_method = :sendmail # Defaults to: # # config.action_mailer.sendmail_settings = { diff --git a/config/initializers/grit_ext.rb b/config/initializers/grit_ext.rb index 9231da6f..1a7e6361 100644 --- a/config/initializers/grit_ext.rb +++ b/config/initializers/grit_ext.rb @@ -7,6 +7,6 @@ Grit::Blob.class_eval do include Utils::Colorize end -Grit::Commit.class_eval do +Grit::Commit.class_eval do include CommitExt end diff --git a/config/routes.rb b/config/routes.rb index 8a40a8fe..21a0729c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ Gitlab::Application.routes.draw do - namespace :admin do + namespace :admin do resources :users resources :projects resources :team_members @@ -10,7 +10,7 @@ Gitlab::Application.routes.draw do root :to => "users#index" end - get "errors/gitosis" + get "errors/gitosis" get "profile/password", :to => "profile#password" put "profile/password", :to => "profile#password_update" put "profile/edit", :to => "profile#social_update" @@ -21,8 +21,8 @@ Gitlab::Application.routes.draw do resources :keys devise_for :users - resources :projects, :except => [:new, :create, :index], :path => "/" do - member do + resources :projects, :except => [:new, :create, :index], :path => "/" do + member do get "tree" get "blob" get "team" @@ -32,7 +32,7 @@ Gitlab::Application.routes.draw do get "tree/:commit_id" => "projects#tree" get "tree/:commit_id/:path" => "projects#tree", :as => :tree_file, - :constraints => { + :constraints => { :id => /[a-zA-Z0-9_\-]+/, :commit_id => /[a-zA-Z0-9]+/, :path => /.*/ diff --git a/db/migrate/20110913200833_devise_create_users.rb b/db/migrate/20110913200833_devise_create_users.rb index 3083e742..01869a9e 100644 --- a/db/migrate/20110913200833_devise_create_users.rb +++ b/db/migrate/20110913200833_devise_create_users.rb @@ -11,7 +11,6 @@ class DeviseCreateUsers < ActiveRecord::Migration # t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both # t.token_authenticatable - t.timestamps end diff --git a/lib/color.rb b/lib/color.rb index 23feecf4..4eabe249 100644 --- a/lib/color.rb +++ b/lib/color.rb @@ -17,7 +17,7 @@ module Color def command(string) `#{string}` - if $?.to_i > 0 + if $?.to_i > 0 puts red " == #{string} - FAIL" puts red " == Error during configure" exit diff --git a/lib/commit_ext.rb b/lib/commit_ext.rb index e09dbdaf..411809f0 100644 --- a/lib/commit_ext.rb +++ b/lib/commit_ext.rb @@ -1,11 +1,11 @@ module CommitExt def safe_message - message.encode("UTF-8", - :invalid => :replace, - :undef => :replace, + message.encode("UTF-8", + :invalid => :replace, + :undef => :replace, :universal_newline => true, :replace => "") - rescue + rescue "-- invalid encoding for commit message" end end diff --git a/lib/file_size_validator.rb b/lib/file_size_validator.rb index 151e0ce5..611e584f 100644 --- a/lib/file_size_validator.rb +++ b/lib/file_size_validator.rb @@ -33,7 +33,7 @@ class FileSizeValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) raise(ArgumentError, "A CarrierWave::Uploader::Base object was expected") unless value.kind_of? CarrierWave::Uploader::Base - + value = (options[:tokenizer] || DEFAULT_TOKENIZER).call(value) if value.kind_of?(String) CHECKS.each do |key, validity_check| @@ -53,7 +53,7 @@ class FileSizeValidator < ActiveModel::EachValidator record.errors.add(attribute, MESSAGES[key], errors_options) end end - + def help Helper.instance end diff --git a/lib/utils.rb b/lib/utils.rb index e57121a3..f43e2edd 100644 --- a/lib/utils.rb +++ b/lib/utils.rb @@ -1,8 +1,8 @@ module Utils module FileHelper - def binary?(string) + def binary?(string) string.each_byte do |x| - x.nonzero? or return true + x.nonzero? or return true end false end diff --git a/public/index.html.example b/public/index.html.example index 9d9811a5..16248eda 100644 --- a/public/index.html.example +++ b/public/index.html.example @@ -25,7 +25,6 @@ text-decoration: none; } - #page { background-color: #f0f0f0; width: 750px; @@ -57,7 +56,6 @@ padding-right: 30px; } - #header { background-image: url("/assets/rails.png"); background-repeat: no-repeat; @@ -71,7 +69,6 @@ font-size: 16px; } - #about h3 { margin: 0; margin-bottom: 10px; @@ -112,7 +109,6 @@ padding: 10px; } - #getting-started { border-top: 1px solid #ccc; margin-top: 25px; @@ -149,7 +145,6 @@ font-size: 13px; } - #sidebar ul { margin-left: 0; padding-left: 0; diff --git a/spec/factory.rb b/spec/factory.rb index 29e552b1..5edef358 100644 --- a/spec/factory.rb +++ b/spec/factory.rb @@ -1,7 +1,7 @@ class Factory @factories = {} - class << self + class << self def add(name, klass, &block) @factories[name] = [klass, block] end @@ -13,10 +13,10 @@ class Factory def new(name, opts) factory = @factories[name] factory[0].new.tap do |obj| - factory[1].call(obj) + factory[1].call(obj) end.tap do |obj| opts.each do |k, opt| - obj.send("#{k}=", opt) + obj.send("#{k}=", opt) end end end diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index b2d594c9..e0559ab6 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -14,7 +14,7 @@ describe Issue do it { should validate_presence_of(:assignee_id) } end - describe "Scope" do + describe "Scope" do it { Issue.should respond_to :closed } it { Issue.should respond_to :opened } end diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 8515f19b..6522b825 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -10,7 +10,7 @@ describe Key do it { should validate_presence_of(:key) } end - describe "Methods" do + describe "Methods" do it { should respond_to :projects } end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 20bd41ad..5b16ad36 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -13,8 +13,8 @@ describe Note do it { Factory.create(:note, :project => Factory.create(:project)).should be_valid } - describe :authorization do - before do + describe :authorization do + before do @p1 = Factory :project @p2 = Factory :project, :code => "alien", :path => "legit_1" @u1 = Factory :user @@ -24,10 +24,10 @@ describe Note do @abilities << Ability end - describe :read do - before do - @p1.users_projects.create(:user => @u1, :read => false) - @p1.users_projects.create(:user => @u2, :read => true) + describe :read do + before do + @p1.users_projects.create(:user => @u1, :read => false) + @p1.users_projects.create(:user => @u2, :read => true) @p2.users_projects.create(:user => @u3, :read => true) end @@ -36,11 +36,11 @@ describe Note do it { @abilities.allowed?(@u3, :read_note, @p1).should be_false } end - describe :write do - before do - @p1.users_projects.create(:user => @u1, :write => false) - @p1.users_projects.create(:user => @u2, :write => true) - @p2.users_projects.create(:user => @u3, :write => true) + describe :write do + before do + @p1.users_projects.create(:user => @u1, :write => false) + @p1.users_projects.create(:user => @u2, :write => true) + @p2.users_projects.create(:user => @u3, :write => true) end it { @abilities.allowed?(@u1, :write_note, @p1).should be_false } @@ -48,11 +48,11 @@ describe Note do it { @abilities.allowed?(@u3, :write_note, @p1).should be_false } end - describe :admin do - before do - @p1.users_projects.create(:user => @u1, :admin => false) - @p1.users_projects.create(:user => @u2, :admin => true) - @p2.users_projects.create(:user => @u3, :admin => true) + describe :admin do + before do + @p1.users_projects.create(:user => @u1, :admin => false) + @p1.users_projects.create(:user => @u2, :admin => true) + @p2.users_projects.create(:user => @u3, :admin => true) end it { @abilities.allowed?(@u1, :admin_note, @p1).should be_false } diff --git a/spec/models/project_security_spec.rb b/spec/models/project_security_spec.rb index 8eb8ee80..f8029463 100644 --- a/spec/models/project_security_spec.rb +++ b/spec/models/project_security_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' describe Project do - describe :authorization do - before do + describe :authorization do + before do @p1 = Factory :project @u1 = Factory :user @u2 = Factory :user @@ -10,30 +10,30 @@ describe Project do @abilities << Ability end - describe :read do - before do - @p1.users_projects.create(:project => @p1, :user => @u1, :read => false) - @p1.users_projects.create(:project => @p1, :user => @u2, :read => true) + describe :read do + before do + @p1.users_projects.create(:project => @p1, :user => @u1, :read => false) + @p1.users_projects.create(:project => @p1, :user => @u2, :read => true) end it { @abilities.allowed?(@u1, :read_project, @p1).should be_false } it { @abilities.allowed?(@u2, :read_project, @p1).should be_true } end - describe :write do - before do - @p1.users_projects.create(:project => @p1, :user => @u1, :write => false) - @p1.users_projects.create(:project => @p1, :user => @u2, :write => true) + describe :write do + before do + @p1.users_projects.create(:project => @p1, :user => @u1, :write => false) + @p1.users_projects.create(:project => @p1, :user => @u2, :write => true) end it { @abilities.allowed?(@u1, :write_project, @p1).should be_false } it { @abilities.allowed?(@u2, :write_project, @p1).should be_true } end - describe :admin do - before do - @p1.users_projects.create(:project => @p1, :user => @u1, :admin => false) - @p1.users_projects.create(:project => @p1, :user => @u2, :admin => true) + describe :admin do + before do + @p1.users_projects.create(:project => @p1, :user => @u1, :admin => false) + @p1.users_projects.create(:project => @p1, :user => @u2, :admin => true) end it { @abilities.allowed?(@u1, :admin_project, @p1).should be_false } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 0c62743d..7bce57e8 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -40,20 +40,20 @@ describe Project do should_not allow_value("gitosis-admin").for(:path) end - it "should return valid url to repo" do + it "should return valid url to repo" do project = Project.new(:path => "somewhere") project.url_to_repo.should == "git@localhost:somewhere.git" end - it "should return path to repo" do + it "should return path to repo" do project = Project.new(:path => "somewhere") project.path_to_repo.should == File.join(Rails.root, "tmp", "tests", "somewhere") end - describe :valid_repo? do - it "should be valid repo" do + describe :valid_repo? do + it "should be valid repo" do project = Factory :project - project.valid_repo?.should be_true + project.valid_repo?.should be_true end it "should be invalid repo" do @@ -62,43 +62,43 @@ describe Project do end end - describe "Git methods" do + describe "Git methods" do let(:project) { Factory :project } - describe :repo do - it "should return valid repo" do + describe :repo do + it "should return valid repo" do project.repo.should be_kind_of(Grit::Repo) end - it "should return nil" do + it "should return nil" do lambda { Project.new(:path => "invalid").repo }.should raise_error(Grit::NoSuchPathError) end - it "should return nil" do + it "should return nil" do lambda { Project.new.repo }.should raise_error(TypeError) end end - describe :commit do - it "should return first head commit if without params" do + describe :commit do + it "should return first head commit if without params" do project.commit.id.should == project.repo.commits.first.id end - it "should return valid commit" do + it "should return valid commit" do project.commit(ValidCommit::ID).should be_valid_commit end - it "should return nil" do + it "should return nil" do project.commit("+123_4532530XYZ").should be_nil end end - describe :tree do - before do + describe :tree do + before do @commit = project.commit(ValidCommit::ID) end - it "should raise error w/o arguments" do + it "should raise error w/o arguments" do lambda { project.tree }.should raise_error end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 32fb90a3..d66b1c25 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -14,7 +14,7 @@ describe User do it { should respond_to(:name) } end - it "should return valid identifier" do + it "should return valid identifier" do user = User.new(:email => "test@mail.com") user.identifier.should == "test_mail.com" end diff --git a/spec/models/users_project_spec.rb b/spec/models/users_project_spec.rb index d6a4d02b..c1539161 100644 --- a/spec/models/users_project_spec.rb +++ b/spec/models/users_project_spec.rb @@ -11,7 +11,7 @@ describe UsersProject do it { should validate_presence_of(:project_id) } end - describe "Delegate methods" do + describe "Delegate methods" do it { should respond_to(:user_name) } it { should respond_to(:user_email) } end diff --git a/spec/monkeypatch.rb b/spec/monkeypatch.rb index ea42337f..2e491496 100644 --- a/spec/monkeypatch.rb +++ b/spec/monkeypatch.rb @@ -1,6 +1,6 @@ # Stubbing Project <-> gitosis path # create project using Factory only -class Project +class Project def update_gitosis_project true end @@ -9,12 +9,12 @@ class Project true end - def path_to_repo + def path_to_repo File.join(Rails.root, "tmp", "tests", path) end end -class Key +class Key def update_gitosis true end diff --git a/spec/requests/admin/admin_projects_spec.rb b/spec/requests/admin/admin_projects_spec.rb index e36ee441..fd8703ec 100644 --- a/spec/requests/admin/admin_projects_spec.rb +++ b/spec/requests/admin/admin_projects_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe "Admin::Projects" do - before do + before do @project = Factory :project, :name => "LeGiT", :code => "LGT" @@ -9,7 +9,7 @@ describe "Admin::Projects" do end describe "GET /admin/projects" do - before do + before do visit admin_projects_path end @@ -17,49 +17,49 @@ describe "Admin::Projects" do current_path.should == admin_projects_path end - it "should have projects list" do + it "should have projects list" do page.should have_content(@project.code) page.should have_content(@project.name) end end - describe "GET /admin/projects/:id" do - before do + describe "GET /admin/projects/:id" do + before do visit admin_projects_path click_link "Show" end - it "should have project info" do + it "should have project info" do page.should have_content(@project.code) page.should have_content(@project.name) end end - describe "GET /admin/projects/:id/edit" do - before do + describe "GET /admin/projects/:id/edit" do + before do visit admin_projects_path click_link "edit_project_#{@project.id}" end - it "should have project edit page" do + it "should have project edit page" do page.should have_content("Name") page.should have_content("Code") end describe "Update project" do - before do + before do fill_in "project_name", :with => "Big Bang" fill_in "project_code", :with => "BB1" click_button "Save" @project.reload end - it "should show page with new data" do + it "should show page with new data" do page.should have_content("BB1") page.should have_content("Big Bang") end - it "should change project entry" do + it "should change project entry" do @project.name.should == "Big Bang" @project.code.should == "BB1" end @@ -67,24 +67,24 @@ describe "Admin::Projects" do end describe "GET /admin/projects/new" do - before do + before do visit admin_projects_path click_link "New Project" end it "should be correct path" do - current_path.should == new_admin_project_path + current_path.should == new_admin_project_path end it "should have labels for new project" do - page.should have_content("Name") - page.should have_content("Path") - page.should have_content("Description") + page.should have_content("Name") + page.should have_content("Path") + page.should have_content("Description") end end describe "POST /admin/projects" do - before do + before do visit new_admin_project_path fill_in 'Name', :with => 'NewProject' fill_in 'Code', :with => 'NPR' diff --git a/spec/requests/admin/admin_users_spec.rb b/spec/requests/admin/admin_users_spec.rb index 8d9cbcae..67cfde5f 100644 --- a/spec/requests/admin/admin_users_spec.rb +++ b/spec/requests/admin/admin_users_spec.rb @@ -4,7 +4,7 @@ describe "Admin::Users" do before { login_as :admin } describe "GET /admin/users" do - before do + before do visit admin_users_path end @@ -12,14 +12,14 @@ describe "Admin::Users" do current_path.should == admin_users_path end - it "should have users list" do + it "should have users list" do page.should have_content(@user.email) page.should have_content(@user.name) end end - describe "GET /admin/users/new" do - before do + describe "GET /admin/users/new" do + before do @password = "123ABC" visit new_admin_user_path fill_in "user_name", :with => "Big Bang" @@ -28,23 +28,23 @@ describe "Admin::Users" do fill_in "user_password_confirmation", :with => @password end - it "should create new user" do + it "should create new user" do expect { click_button "Save" }.to change {User.count}.by(1) end - it "should create user with valid data" do + it "should create user with valid data" do click_button "Save" user = User.last user.name.should == "Big Bang" user.email.should == "bigbang@mail.com" end - it "should call send mail" do + it "should call send mail" do Notify.should_receive(:new_user_email).and_return(stub(:deliver => true)) click_button "Save" end - it "should send valid email to user with email & password" do + it "should send valid email to user with email & password" do click_button "Save" user = User.last email = ActionMailer::Base.deliveries.last @@ -54,45 +54,45 @@ describe "Admin::Users" do end end - describe "GET /admin/users/:id" do - before do + describe "GET /admin/users/:id" do + before do visit admin_users_path click_link "Show" end - it "should have user info" do + it "should have user info" do page.should have_content(@user.email) page.should have_content(@user.name) page.should have_content(@user.is_admin?) end end - describe "GET /admin/users/:id/edit" do - before do + describe "GET /admin/users/:id/edit" do + before do @simple_user = Factory :user visit admin_users_path click_link "edit_user_#{@simple_user.id}" end - it "should have user edit page" do + it "should have user edit page" do page.should have_content("Name") page.should have_content("Password") end describe "Update user" do - before do + before do fill_in "user_name", :with => "Big Bang" fill_in "user_email", :with => "bigbang@mail.com" check "user_admin" click_button "Save" end - it "should show page with new data" do + it "should show page with new data" do page.should have_content("bigbang@mail.com") page.should have_content("Big Bang") end - it "should change user entry" do + it "should change user entry" do @simple_user.reload @simple_user.name.should == "Big Bang" @simple_user.is_admin?.should be_true diff --git a/spec/requests/admin/security_spec.rb b/spec/requests/admin/security_spec.rb index 743f9f08..27b60196 100644 --- a/spec/requests/admin/security_spec.rb +++ b/spec/requests/admin/security_spec.rb @@ -1,25 +1,25 @@ require 'spec_helper' describe "Admin::Projects" do - describe "GET /admin/projects" do + describe "GET /admin/projects" do it { admin_projects_path.should be_allowed_for :admin } it { admin_projects_path.should be_denied_for :user } it { admin_projects_path.should be_denied_for :visitor } end - describe "GET /admin/users" do + describe "GET /admin/users" do it { admin_users_path.should be_allowed_for :admin } it { admin_users_path.should be_denied_for :user } it { admin_users_path.should be_denied_for :visitor } end - describe "GET /admin/team_members" do + describe "GET /admin/team_members" do it { admin_team_members_path.should be_allowed_for :admin } it { admin_team_members_path.should be_denied_for :user } it { admin_team_members_path.should be_denied_for :visitor } end - describe "GET /admin/emails" do + describe "GET /admin/emails" do it { admin_emails_path.should be_allowed_for :admin } it { admin_emails_path.should be_denied_for :user } it { admin_emails_path.should be_denied_for :visitor } diff --git a/spec/requests/commits_notes_spec.rb b/spec/requests/commits_notes_spec.rb index 522fe518..c424f4fc 100644 --- a/spec/requests/commits_notes_spec.rb +++ b/spec/requests/commits_notes_spec.rb @@ -4,13 +4,13 @@ describe "Issues" do let(:project) { Factory :project } let!(:commit) { project.repo.commits.first } - before do + before do login_as :user project.add_access(@user, :read, :write) end - describe "add new note", :js => true do - before do + describe "add new note", :js => true do + before do visit project_commit_path(project, commit) click_link "Comments" # notes tab fill_in "note_note", :with => "I commented this commit" diff --git a/spec/requests/commits_spec.rb b/spec/requests/commits_spec.rb index cd7314f9..79bb03f5 100644 --- a/spec/requests/commits_spec.rb +++ b/spec/requests/commits_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' describe "Commits" do let(:project) { Factory :project } let!(:commit) { project.repo.commits.first } - before do + before do login_as :user project.add_access(@user, :read) end describe "GET /commits" do - before do + before do visit project_commits_path(project) end @@ -17,22 +17,22 @@ describe "Commits" do current_path.should == project_commits_path(project) end - it "should have project name" do + it "should have project name" do page.should have_content(project.name) end - it "should list commits" do + it "should list commits" do page.should have_content(commit.author) page.should have_content(commit.message) end end - describe "GET /commits/:id" do - before do + describe "GET /commits/:id" do + before do visit project_commit_path(project, commit) end - it "should have valid path" do + it "should have valid path" do current_path.should == project_commit_path(project, commit) end end diff --git a/spec/requests/issues_notes_spec.rb b/spec/requests/issues_notes_spec.rb index 95eb2f35..9ebad394 100644 --- a/spec/requests/issues_notes_spec.rb +++ b/spec/requests/issues_notes_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe "Issues" do let(:project) { Factory :project } - before do + before do login_as :user project.add_access(@user, :read, :write) @@ -13,8 +13,8 @@ describe "Issues" do :project => project end - describe "add new note", :js => true do - before do + describe "add new note", :js => true do + before do visit project_issue_path(project, @issue) fill_in "note_note", :with => "I commented this issue" click_button "Add note" diff --git a/spec/requests/issues_spec.rb b/spec/requests/issues_spec.rb index 79fdf5ef..8c090d7f 100644 --- a/spec/requests/issues_spec.rb +++ b/spec/requests/issues_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' describe "Issues" do let(:project) { Factory :project } - before do + before do login_as :user project.add_access(@user, :read, :write) end describe "GET /issues" do - before do + before do @issue = Factory :issue, :author => @user, :assignee => @user, @@ -24,23 +24,23 @@ describe "Issues" do it { should have_content(@issue.project.name) } it { should have_content(@issue.assignee.name) } - describe "Destroy" do - before do + describe "Destroy" do + before do # admin access to remove issue @user.users_projects.destroy_all project.add_access(@user, :read, :write, :admin) visit project_issues_path(project) end - it "should remove entry" do + it "should remove entry" do expect { click_link "destroy_issue_#{@issue.id}" }.to change { Issue.count }.by(-1) end end - describe "statuses", :js => true do - before do + describe "statuses", :js => true do + before do @closed_issue = Factory :issue, :author => @user, :assignee => @user, @@ -48,18 +48,18 @@ describe "Issues" do :closed => true end - it "should show only open" do + it "should show only open" do should have_content(@issue.title) should have_no_content(@closed_issue.title) end - it "should show only closed" do + it "should show only closed" do choose "closed_issues" should have_no_content(@issue.title) should have_content(@closed_issue.title) end - it "should show all" do + it "should show all" do choose "all_issues" should have_content(@issue.title) should have_content(@closed_issue.title) @@ -67,17 +67,17 @@ describe "Issues" do end end - describe "New issue", :js => true do - before do + describe "New issue", :js => true do + before do visit project_issues_path(project) click_link "New Issue" end - it "should open new issue popup" do + it "should open new issue popup" do page.should have_content("Add new issue") end - describe "fill in" do + describe "fill in" do before do fill_in "issue_title", :with => "bug 345" fill_in "issue_content", :with => "app bug 345" @@ -87,7 +87,7 @@ describe "Issues" do it { expect { click_button "Save" }.to change {Issue.count}.by(1) } - it "should add new issue to table" do + it "should add new issue to table" do click_button "Save" page.should_not have_content("Add new issue") @@ -96,12 +96,12 @@ describe "Issues" do page.should have_content project.name end - it "should call send mail" do + it "should call send mail" do Notify.should_receive(:new_issue_email).and_return(stub(:deliver => true)) click_button "Save" end - it "should send valid email to user with email & password" do + it "should send valid email to user with email & password" do click_button "Save" issue = Issue.last email = ActionMailer::Base.deliveries.last @@ -112,8 +112,8 @@ describe "Issues" do end end - describe "Edit issue", :js => true do - before do + describe "Edit issue", :js => true do + before do @issue = Factory :issue, :author => @user, :assignee => @user, @@ -122,11 +122,11 @@ describe "Issues" do click_link "Edit" end - it "should open new issue popup" do + it "should open new issue popup" do page.should have_content("Issue ##{@issue.id}") end - describe "fill in" do + describe "fill in" do before do fill_in "issue_title", :with => "bug 345" fill_in "issue_content", :with => "app bug 345" @@ -134,7 +134,7 @@ describe "Issues" do it { expect { click_button "Save" }.to_not change {Issue.count} } - it "should update issue fields" do + it "should update issue fields" do click_button "Save" page.should_not have_content("Issue ##{@issue.id}") diff --git a/spec/requests/keys_spec.rb b/spec/requests/keys_spec.rb index 316115f9..6ce22b30 100644 --- a/spec/requests/keys_spec.rb +++ b/spec/requests/keys_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' describe "Issues" do - before do + before do login_as :user end describe "GET /keys" do - before do + before do @key = Factory :key, :user => @user visit keys_path end @@ -15,8 +15,8 @@ describe "Issues" do it { should have_content(@key.title) } - describe "Destroy" do - it "should remove entry" do + describe "Destroy" do + it "should remove entry" do expect { click_link "destroy_key_#{@key.id}" }.to change { @user.keys.count }.by(-1) @@ -24,17 +24,17 @@ describe "Issues" do end end - describe "New key", :js => true do - before do + describe "New key", :js => true do + before do visit keys_path click_link "Add new" end - it "should open new key popup" do + it "should open new key popup" do page.should have_content("Add new public key") end - describe "fill in" do + describe "fill in" do before do fill_in "key_title", :with => "laptop" fill_in "key_key", :with => "publickey234=" @@ -42,7 +42,7 @@ describe "Issues" do it { expect { click_button "Save" }.to change {Key.count}.by(1) } - it "should add new key to table" do + it "should add new key to table" do click_button "Save" page.should_not have_content("Add new public key") diff --git a/spec/requests/profile_spec.rb b/spec/requests/profile_spec.rb index 5838f63b..eca1c12e 100644 --- a/spec/requests/profile_spec.rb +++ b/spec/requests/profile_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' describe "Profile" do - before do + before do login_as :user end describe "Show profile" do - before do + before do visit profile_path end @@ -15,13 +15,13 @@ describe "Profile" do end describe "Profile update" do - before do + before do visit profile_path fill_in "user_skype", :with => "testskype" - fill_in "user_linkedin", :with => "testlinkedin" + fill_in "user_linkedin", :with => "testlinkedin" fill_in "user_twitter", :with => "testtwitter" click_button "Save" - @user.reload + @user.reload end it { @user.skype.should == 'testskype' } @@ -29,18 +29,17 @@ describe "Profile" do it { @user.twitter.should == 'testtwitter' } end - describe "Password update" do - before do + before do visit profile_password_path end it { page.should have_content("Password") } it { page.should have_content("Password confirmation") } - describe "change password" do - before do - @old_pwd = @user.encrypted_password + describe "change password" do + before do + @old_pwd = @user.encrypted_password fill_in "user_password", :with => "777777" fill_in "user_password_confirmation", :with => "777777" click_button "Save" @@ -51,18 +50,18 @@ describe "Profile" do current_path.should == new_user_session_path end - it "should change password" do + it "should change password" do @user.encrypted_password.should_not == @old_pwd end - describe "login with new password" do + describe "login with new password" do before do fill_in "user_email", :with => @user.email fill_in "user_password", :with => "777777" click_button "Sign in" end - - it "should login user" do + + it "should login user" do current_path.should == root_path end end diff --git a/spec/requests/projects_security_spec.rb b/spec/requests/projects_security_spec.rb index 90f88d88..1d42c5e7 100644 --- a/spec/requests/projects_security_spec.rb +++ b/spec/requests/projects_security_spec.rb @@ -1,33 +1,33 @@ require 'spec_helper' describe "Projects" do - describe "GET /projects" do + describe "GET /projects" do it { projects_path.should be_allowed_for :admin } it { projects_path.should be_allowed_for :user } it { projects_path.should be_denied_for :visitor } end - describe "GET /projects/new" do + describe "GET /projects/new" do it { projects_path.should be_allowed_for :admin } it { projects_path.should be_allowed_for :user } it { projects_path.should be_denied_for :visitor } end describe "Project" do - before do + before do @project = Factory :project @u1 = Factory :user @u2 = Factory :user @u3 = Factory :user # full access - @project.users_projects.create(:user => @u1, :read => true, :write => true, :admin => true) + @project.users_projects.create(:user => @u1, :read => true, :write => true, :admin => true) # no access - @project.users_projects.create(:user => @u2, :read => false, :write => false, :admin => false) + @project.users_projects.create(:user => @u2, :read => false, :write => false, :admin => false) # readonly - @project.users_projects.create(:user => @u3, :read => true, :write => false, :admin => false) + @project.users_projects.create(:user => @u3, :read => true, :write => false, :admin => false) end - describe "GET /project_code" do + describe "GET /project_code" do it { project_path(@project).should be_allowed_for @u1 } it { project_path(@project).should be_allowed_for @u3 } it { project_path(@project).should be_denied_for :admin } @@ -36,7 +36,7 @@ describe "Projects" do it { project_path(@project).should be_denied_for :visitor } end - describe "GET /project_code/tree" do + describe "GET /project_code/tree" do it { tree_project_path(@project).should be_allowed_for @u1 } it { tree_project_path(@project).should be_allowed_for @u3 } it { tree_project_path(@project).should be_denied_for :admin } @@ -45,7 +45,7 @@ describe "Projects" do it { tree_project_path(@project).should be_denied_for :visitor } end - describe "GET /project_code/commits" do + describe "GET /project_code/commits" do it { project_commits_path(@project).should be_allowed_for @u1 } it { project_commits_path(@project).should be_allowed_for @u3 } it { project_commits_path(@project).should be_denied_for :admin } @@ -54,7 +54,7 @@ describe "Projects" do it { project_commits_path(@project).should be_denied_for :visitor } end - describe "GET /project_code/commit" do + describe "GET /project_code/commit" do it { project_commit_path(@project, @project.commit).should be_allowed_for @u1 } it { project_commit_path(@project, @project.commit).should be_allowed_for @u3 } it { project_commit_path(@project, @project.commit).should be_denied_for :admin } @@ -63,7 +63,7 @@ describe "Projects" do it { project_commit_path(@project, @project.commit).should be_denied_for :visitor } end - describe "GET /project_code/team" do + describe "GET /project_code/team" do it { team_project_path(@project).should be_allowed_for @u1 } it { team_project_path(@project).should be_allowed_for @u3 } it { team_project_path(@project).should be_denied_for :admin } @@ -72,7 +72,7 @@ describe "Projects" do it { team_project_path(@project).should be_denied_for :visitor } end - describe "GET /project_code/wall" do + describe "GET /project_code/wall" do it { wall_project_path(@project).should be_allowed_for @u1 } it { wall_project_path(@project).should be_allowed_for @u3 } it { wall_project_path(@project).should be_denied_for :admin } @@ -81,8 +81,8 @@ describe "Projects" do it { wall_project_path(@project).should be_denied_for :visitor } end - describe "GET /project_code/blob" do - before do + describe "GET /project_code/blob" do + before do @commit = @project.commit @path = @commit.tree.contents.select { |i| i.is_a?(Grit::Blob)}.first.name @blob_path = blob_project_path(@project, :commit_id => @commit.id, :path => @path) @@ -96,7 +96,7 @@ describe "Projects" do it { @blob_path.should be_denied_for :visitor } end - describe "GET /project_code/edit" do + describe "GET /project_code/edit" do it { edit_project_path(@project).should be_allowed_for @u1 } it { edit_project_path(@project).should be_denied_for @u3 } it { edit_project_path(@project).should be_denied_for :admin } @@ -105,7 +105,7 @@ describe "Projects" do it { edit_project_path(@project).should be_denied_for :visitor } end - describe "GET /project_code/issues" do + describe "GET /project_code/issues" do it { project_issues_path(@project).should be_allowed_for @u1 } it { project_issues_path(@project).should be_allowed_for @u3 } it { project_issues_path(@project).should be_denied_for :admin } @@ -114,7 +114,7 @@ describe "Projects" do it { project_issues_path(@project).should be_denied_for :visitor } end - describe "GET /project_code/snippets" do + describe "GET /project_code/snippets" do it { project_snippets_path(@project).should be_allowed_for @u1 } it { project_snippets_path(@project).should be_allowed_for @u3 } it { project_snippets_path(@project).should be_denied_for :admin } diff --git a/spec/requests/projects_spec.rb b/spec/requests/projects_spec.rb index 945c1ea2..e1e9773c 100644 --- a/spec/requests/projects_spec.rb +++ b/spec/requests/projects_spec.rb @@ -4,38 +4,38 @@ describe "Projects" do before { login_as :user } describe "GET /projects" do - before do + before do visit projects_path end it "should be on projects page" do - current_path.should == projects_path + current_path.should == projects_path end it "should have link to new project" do - page.should have_content("New Project") + page.should have_content("New Project") end end describe "GET /projects/new" do - before do + before do visit projects_path click_link "New Project" end it "should be correct path" do - current_path.should == new_project_path + current_path.should == new_project_path end it "should have labels for new project" do - page.should have_content("Name") - page.should have_content("Path") - page.should have_content("Description") + page.should have_content("Name") + page.should have_content("Path") + page.should have_content("Description") end end describe "POST /projects" do - before do + before do visit new_project_path fill_in 'Name', :with => 'NewProject' fill_in 'Code', :with => 'NPR' @@ -61,7 +61,7 @@ describe "Projects" do end describe "GET /projects/show" do - before do + before do @project = Factory :project @project.add_access(@user, :read) @@ -72,14 +72,14 @@ describe "Projects" do current_path.should == project_path(@project) end - it "should beahave like dashboard" do + it "should beahave like dashboard" do page.should have_content("History") end end describe "GET /projects/team" do - before do + before do @project = Factory :project @project.add_access(@user, :read) @@ -92,13 +92,13 @@ describe "Projects" do current_path.should == team_project_path(@project) end - it "should have as as team member" do + it "should have as as team member" do page.should have_content(@user.name) end end describe "GET /projects/:id/edit" do - before do + before do @project = Factory :project @project.add_access(@user, :admin, :read) @@ -110,14 +110,14 @@ describe "Projects" do end it "should have labels for new project" do - page.should have_content("Name") - page.should have_content("Path") - page.should have_content("Description") + page.should have_content("Name") + page.should have_content("Path") + page.should have_content("Description") end end describe "PUT /projects/:id" do - before do + before do @project = Factory :project @project.add_access(@user, :admin, :read) @@ -140,14 +140,14 @@ describe "Projects" do end #describe "DELETE /projects/:id", :js => true do - #before do + #before do #@project = Factory :project #@project.add_access(@user, :read, :admin) #visit projects_path #end #it "should be correct path" do - #expect { click_link "Destroy" }.to change {Project.count}.by(1) + #expect { click_link "Destroy" }.to change {Project.count}.by(1) #end #end end diff --git a/spec/requests/projects_tree_perfomance_spec.rb b/spec/requests/projects_tree_perfomance_spec.rb index 5b4facb1..bf3ca167 100644 --- a/spec/requests/projects_tree_perfomance_spec.rb +++ b/spec/requests/projects_tree_perfomance_spec.rb @@ -6,13 +6,13 @@ describe "Projects" do describe "GET /projects/tree" do describe "head" do - before do + before do @project = Factory :project @project.add_access(@user, :read) end - it "should be fast" do + it "should be fast" do time = Benchmark.realtime do visit tree_project_path(@project) end @@ -21,12 +21,12 @@ describe "Projects" do end describe ValidCommit::ID do - before do + before do @project = Factory :project @project.add_access(@user, :read) end - it "should be fast" do + it "should be fast" do time = Benchmark.realtime do visit tree_project_path(@project, :commit_id => ValidCommit::ID) end diff --git a/spec/requests/projects_tree_spec.rb b/spec/requests/projects_tree_spec.rb index 4e3176bb..fd49ffaa 100644 --- a/spec/requests/projects_tree_spec.rb +++ b/spec/requests/projects_tree_spec.rb @@ -5,7 +5,7 @@ describe "Projects" do describe "GET /projects/tree" do describe "head" do - before do + before do @project = Factory :project @project.add_access(@user, :read) @@ -20,7 +20,7 @@ describe "Projects" do end describe ValidCommit::ID do - before do + before do @project = Factory :project @project.add_access(@user, :read) @@ -36,7 +36,7 @@ describe "Projects" do end describe "branch passed" do - before do + before do @project = Factory :project @project.add_access(@user, :read) @@ -53,7 +53,7 @@ describe "Projects" do # TREE FILE PREVIEW describe "file preview" do - before do + before do @project = Factory :project @project.add_access(@user, :read) @@ -70,9 +70,9 @@ describe "Projects" do end end - # RAW FILE + # RAW FILE describe "GET /projects/blob" do - before do + before do @project = Factory :project @project.add_access(@user, :read) @@ -85,7 +85,7 @@ describe "Projects" do current_path.should == blob_project_path(@project) end - it "raw file response" do + it "raw file response" do page.source.should == ValidCommit::BLOB_FILE end end diff --git a/spec/requests/projects_wall_spec.rb b/spec/requests/projects_wall_spec.rb index a7387f93..bb734bda 100644 --- a/spec/requests/projects_wall_spec.rb +++ b/spec/requests/projects_wall_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' describe "Projects", "Wall" do let(:project) { Factory :project } - before do + before do login_as :user project.add_access(@user, :read, :write) end describe "View notes on wall" do - before do + before do Factory :note, :project => project, :note => "Project specs", :author => @user visit wall_project_path(project) end @@ -19,8 +19,8 @@ describe "Projects", "Wall" do it { page.should have_content("less than a minute ago") } end - describe "add new note", :js => true do - before do + describe "add new note", :js => true do + before do visit wall_project_path(project) fill_in "note_note", :with => "my post on wall" click_button "Add note" diff --git a/spec/requests/snippets_spec.rb b/spec/requests/snippets_spec.rb index 00ae58da..d4811958 100644 --- a/spec/requests/snippets_spec.rb +++ b/spec/requests/snippets_spec.rb @@ -3,13 +3,13 @@ require 'spec_helper' describe "Snippets" do let(:project) { Factory :project } - before do + before do login_as :user project.add_access(@user, :read, :write) end describe "GET /snippets" do - before do + before do @snippet = Factory :snippet, :author => @user, :project => project @@ -23,15 +23,15 @@ describe "Snippets" do it { should have_content(@snippet.project.name) } it { should have_content(@snippet.author.name) } - describe "Destroy" do - before do + describe "Destroy" do + before do # admin access to remove snippet @user.users_projects.destroy_all project.add_access(@user, :read, :write, :admin) visit project_snippets_path(project) end - it "should remove entry" do + it "should remove entry" do expect { click_link "destroy_snippet_#{@snippet.id}" }.to change { Snippet.count }.by(-1) @@ -39,17 +39,17 @@ describe "Snippets" do end end - describe "New snippet" do - before do + describe "New snippet" do + before do visit project_snippets_path(project) click_link "New Snippet" end - it "should open new snippet popup" do + it "should open new snippet popup" do page.current_path.should == new_project_snippet_path(project) end - describe "fill in" do + describe "fill in" do before do fill_in "snippet_title", :with => "login function" fill_in "snippet_file_name", :with => "test.rb" @@ -58,7 +58,7 @@ describe "Snippets" do it { expect { click_button "Save" }.to change {Snippet.count}.by(1) } - it "should add new snippet to table" do + it "should add new snippet to table" do click_button "Save" page.current_path.should == project_snippet_path(project, Snippet.last) page.should have_content "login function" @@ -67,8 +67,8 @@ describe "Snippets" do end end - describe "Edit snippet" do - before do + describe "Edit snippet" do + before do @snippet = Factory :snippet, :author => @user, :project => project @@ -76,11 +76,11 @@ describe "Snippets" do click_link "Edit" end - it "should open edit page" do + it "should open edit page" do page.current_path.should == edit_project_snippet_path(project, @snippet) end - describe "fill in" do + describe "fill in" do before do fill_in "snippet_title", :with => "login function" fill_in "snippet_file_name", :with => "test.rb" @@ -89,7 +89,7 @@ describe "Snippets" do it { expect { click_button "Save" }.to_not change {Snippet.count} } - it "should update snippet fields" do + it "should update snippet fields" do click_button "Save" page.current_path.should == project_snippet_path(project, @snippet) diff --git a/spec/requests/team_members_spec.rb b/spec/requests/team_members_spec.rb index 650ed449..d6555518 100644 --- a/spec/requests/team_members_spec.rb +++ b/spec/requests/team_members_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe "TeamMembers" do - before do + before do login_as :user @project = Factory :project @project.add_access(@user, :read, :admin) @@ -10,7 +10,7 @@ describe "TeamMembers" do describe "View profile" do it "should be available" do visit(team_project_path(@project)) - within "#team-table" do + within "#team-table" do click_link(@user.name) end page.should have_content @user.skype @@ -18,23 +18,23 @@ describe "TeamMembers" do end end - describe "New Team member", :js => true do - before do + describe "New Team member", :js => true do + before do @user_1 = Factory :user visit team_project_path(@project) click_link "Add new" end - it "should open new team member popup" do + it "should open new team member popup" do page.should have_content("Add new member to project") end - describe "fill in" do + describe "fill in" do before do click_link "Select user" click_link @user_1.name - within "#team_member_new" do + within "#team_member_new" do check "team_member_read" check "team_member_write" end @@ -42,7 +42,7 @@ describe "TeamMembers" do it { expect { click_button "Save";sleep(1) }.to change {UsersProject.count}.by(1) } - it "should add new member to table" do + it "should add new member to table" do click_button "Save" @member = UsersProject.last @@ -53,8 +53,8 @@ describe "TeamMembers" do @member.admin.should be_false end - it "should not allow creation without access selected" do - within "#team_member_new" do + it "should not allow creation without access selected" do + within "#team_member_new" do uncheck "team_member_read" uncheck "team_member_write" uncheck "team_member_admin" @@ -66,8 +66,8 @@ describe "TeamMembers" do end end - describe "Cancel membership" do - it "should cancel membership" do + describe "Cancel membership" do + it "should cancel membership" do visit team_project_path(@project) expect { click_link "Cancel" }.to change { UsersProject.count }.by(-1) end diff --git a/spec/requests/top_panel_spec.rb b/spec/requests/top_panel_spec.rb index bd4d2047..d1cea6d8 100644 --- a/spec/requests/top_panel_spec.rb +++ b/spec/requests/top_panel_spec.rb @@ -4,7 +4,7 @@ describe "Top Panel", :js => true do before { login_as :user } describe "Search autocomplete" do - before do + before do visit projects_path fill_in "search", :with => "Ke" sleep(2) @@ -12,12 +12,12 @@ describe "Top Panel", :js => true do end it "should be on projects page" do - current_path.should == keys_path + current_path.should == keys_path end end describe "with project" do - before do + before do @project = Factory :project @project.add_access(@user, :read) visit project_path(@project) @@ -28,7 +28,7 @@ describe "Top Panel", :js => true do end it "should be on projects page" do - current_path.should == project_commits_path(@project) + current_path.should == project_commits_path(@project) end end end diff --git a/spec/requests/user_security_spec.rb b/spec/requests/user_security_spec.rb index a27eb1ca..b75a1779 100644 --- a/spec/requests/user_security_spec.rb +++ b/spec/requests/user_security_spec.rb @@ -2,32 +2,32 @@ require 'spec_helper' describe "Users Security" do describe "Project" do - before do + before do @u1 = Factory :user end - describe "GET /login" do + describe "GET /login" do #it { new_user_session_path.should be_denied_for @u1 } #it { new_user_session_path.should be_denied_for :admin } #it { new_user_session_path.should be_denied_for :user } it { new_user_session_path.should_not be_404_for :visitor } end - describe "GET /keys" do + describe "GET /keys" do it { keys_path.should be_allowed_for @u1 } it { keys_path.should be_allowed_for :admin } it { keys_path.should be_allowed_for :user } it { keys_path.should be_denied_for :visitor } end - describe "GET /profile" do + describe "GET /profile" do it { profile_path.should be_allowed_for @u1 } it { profile_path.should be_allowed_for :admin } it { profile_path.should be_allowed_for :user } it { profile_path.should be_denied_for :visitor } end - describe "GET /profile/password" do + describe "GET /profile/password" do it { profile_password_path.should be_allowed_for @u1 } it { profile_password_path.should be_allowed_for :admin } it { profile_password_path.should be_allowed_for :user } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0c2545e3..aa7f23d8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -11,7 +11,6 @@ require 'capybara/dsl' require 'factories' require 'monkeypatch' - # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} diff --git a/spec/support/login.rb b/spec/support/login.rb index 462647ab..a700c8b9 100644 --- a/spec/support/login.rb +++ b/spec/support/login.rb @@ -1,12 +1,12 @@ module LoginMacros def login_as role - @user = User.create(:email => "user#{User.count}@mail.com", + @user = User.create(:email => "user#{User.count}@mail.com", :name => "John Smith", :password => "123456", :password_confirmation => "123456", :skype => 'user_skype') - - if role == :admin + + if role == :admin @user.admin = true @user.save! end @@ -23,7 +23,7 @@ module LoginMacros fill_in "Password", :with => "123456" click_button "Sign in" end - + def logout click_link "Logout" rescue nil end diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index dcdfa6d5..e0672166 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -18,17 +18,17 @@ RSpec::Matchers.define :be_denied_for do |user| match do |url| include UrlAccess url_denied?(user, url) - end + end end RSpec::Matchers.define :be_404_for do |user| match do |url| include UrlAccess url_404?(user, url) - end + end end -module UrlAccess +module UrlAccess def url_allowed?(user, url) emulate_user(user) visit url diff --git a/spec/support/shared_examples.rb b/spec/support/shared_examples.rb index a2e94ac1..118b9b2a 100644 --- a/spec/support/shared_examples.rb +++ b/spec/support/shared_examples.rb @@ -6,13 +6,12 @@ shared_examples_for :project_side_pane do it { should have_content("Tree") } end - shared_examples_for :tree_view do subject { page } it "should have Tree View of project" do - should have_content("app") - should have_content("history") - should have_content("Gemfile") + should have_content("app") + should have_content("history") + should have_content("Gemfile") end end From 3228b62755ed746a88b076c5846ca5d6bdbf94fb Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Wed, 26 Oct 2011 22:17:46 +0500 Subject: [PATCH 107/176] fix repo url selecting on click --- app/assets/javascripts/application.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 024dfe11..41c69119 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -9,7 +9,7 @@ //= require_tree . $(function(){ - $(".one_click_select").click(function(){ + $(".one_click_select").live("click", function(){ $(this).select(); }); From f1e25f25635c64f1c994d01c90a8e50c8be1f81f Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Wed, 26 Oct 2011 22:42:24 +0500 Subject: [PATCH 108/176] move lib assets to vendor directory --- app/assets/javascripts/application.js | 3 +++ app/assets/stylesheets/application.css | 2 ++ .../assets/javascripts/jquery-ui.js | 0 {app => vendor}/assets/javascripts/jquery.cookie.js | 0 {app => vendor}/assets/javascripts/jquery.ui.selectmenu.js | 0 .../jquery-ui-1.8.16.custom.css => jquery-ui/jquery-ui.css} | 0 .../assets/stylesheets/jquery-ui}/jquery.ui.selectmenu.css | 0 7 files changed, 5 insertions(+) rename app/assets/javascripts/jquery-ui-1.8.16.custom.min.js => vendor/assets/javascripts/jquery-ui.js (100%) rename {app => vendor}/assets/javascripts/jquery.cookie.js (100%) rename {app => vendor}/assets/javascripts/jquery.ui.selectmenu.js (100%) rename vendor/assets/stylesheets/{jquery_ui/jquery-ui-1.8.16.custom.css => jquery-ui/jquery-ui.css} (100%) rename {app/assets/stylesheets => vendor/assets/stylesheets/jquery-ui}/jquery.ui.selectmenu.css (100%) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 41c69119..86887fdd 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -5,7 +5,10 @@ // the compiled file. // //= require jquery +//= require jquery-ui //= require jquery_ujs +//= require jquery.ui.selectmenu +//= require jquery.cookie //= require_tree . $(function(){ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index db803ee4..777f3fc1 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -2,6 +2,8 @@ * This is a manifest file that'll automatically include all the stylesheets available in this directory * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at * the top of the compiled file, but it's generally better to create a new file per style scope. + *= require jquery-ui/jquery-ui + *= require jquery-ui/jquery.ui.selectmenu *= require_self *= require_tree . */ diff --git a/app/assets/javascripts/jquery-ui-1.8.16.custom.min.js b/vendor/assets/javascripts/jquery-ui.js similarity index 100% rename from app/assets/javascripts/jquery-ui-1.8.16.custom.min.js rename to vendor/assets/javascripts/jquery-ui.js diff --git a/app/assets/javascripts/jquery.cookie.js b/vendor/assets/javascripts/jquery.cookie.js similarity index 100% rename from app/assets/javascripts/jquery.cookie.js rename to vendor/assets/javascripts/jquery.cookie.js diff --git a/app/assets/javascripts/jquery.ui.selectmenu.js b/vendor/assets/javascripts/jquery.ui.selectmenu.js similarity index 100% rename from app/assets/javascripts/jquery.ui.selectmenu.js rename to vendor/assets/javascripts/jquery.ui.selectmenu.js diff --git a/vendor/assets/stylesheets/jquery_ui/jquery-ui-1.8.16.custom.css b/vendor/assets/stylesheets/jquery-ui/jquery-ui.css similarity index 100% rename from vendor/assets/stylesheets/jquery_ui/jquery-ui-1.8.16.custom.css rename to vendor/assets/stylesheets/jquery-ui/jquery-ui.css diff --git a/app/assets/stylesheets/jquery.ui.selectmenu.css b/vendor/assets/stylesheets/jquery-ui/jquery.ui.selectmenu.css similarity index 100% rename from app/assets/stylesheets/jquery.ui.selectmenu.css rename to vendor/assets/stylesheets/jquery-ui/jquery.ui.selectmenu.css From e0f4a37f3d9fba676c60d28677dfd1d7c9dfd5ac Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Wed, 26 Oct 2011 23:22:42 +0500 Subject: [PATCH 109/176] update project's dashboard every 5 minutes --- app/views/projects/show.html.haml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 85019ecb..56621785 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -21,3 +21,8 @@ %h3 Talk =render "projects/recent_messages" +:javascript + function updateDashboard(){ + $('#content-container').load("#{escape_javascript(project_path(@project))} #content-container>*"); + } + setInterval("updateDashboard()", 300000); From 38cdb3eba0d59f7ffc7fdbb4ca808e759fba504b Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 02:23:04 +0500 Subject: [PATCH 110/176] update shoulda to edge. fixes deprecations --- Gemfile | 2 +- Gemfile.lock | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 77a00659..28168095 100644 --- a/Gemfile +++ b/Gemfile @@ -34,7 +34,7 @@ end group :development, :test do gem 'rspec-rails' - gem 'shoulda' + gem "shoulda", "~> 3.0.0.beta2" gem 'capybara' gem 'autotest' gem 'autotest-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 5ba34459..01ec37e1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -200,7 +200,11 @@ GEM ffi (>= 1.0.7) json_pure rubyzip - shoulda (2.11.3) + shoulda (3.0.0.beta2) + shoulda-context (~> 1.0.0.beta1) + shoulda-matchers (~> 1.0.0.beta1) + shoulda-context (1.0.0.beta1) + shoulda-matchers (1.0.0.beta3) simplecov (0.5.3) multi_json (~> 1.0.3) simplecov-html (~> 0.5.3) @@ -265,7 +269,7 @@ DEPENDENCIES ruby-debug19 sass-rails (~> 3.1.0) seed-fu! - shoulda + shoulda (~> 3.0.0.beta2) simplecov six sqlite3 From 117d1e90fdef3aaf64901ba18a5ce5bab4c668d8 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 10:20:45 +0500 Subject: [PATCH 111/176] add expires_at column to snippets --- db/migrate/20111027051828_add_expires_at_to_snippets.rb | 5 +++++ db/schema.rb | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20111027051828_add_expires_at_to_snippets.rb diff --git a/db/migrate/20111027051828_add_expires_at_to_snippets.rb b/db/migrate/20111027051828_add_expires_at_to_snippets.rb new file mode 100644 index 00000000..0d94b333 --- /dev/null +++ b/db/migrate/20111027051828_add_expires_at_to_snippets.rb @@ -0,0 +1,5 @@ +class AddExpiresAtToSnippets < ActiveRecord::Migration + def change + add_column :snippets, :expires_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index 21c224d4..44b9375a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111025134235) do +ActiveRecord::Schema.define(:version => 20111027051828) do create_table "issues", :force => true do |t| t.string "title" @@ -65,6 +65,7 @@ ActiveRecord::Schema.define(:version => 20111025134235) do t.datetime "created_at" t.datetime "updated_at" t.string "file_name" + t.datetime "expires_at" end create_table "users", :force => true do |t| From 8e1e17763f169f63dc99c7a0f109fe98c87b4064 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 11:46:21 +0500 Subject: [PATCH 112/176] implement snippets lifetime --- app/helpers/snippets_helper.rb | 9 ++++++ app/models/snippet.rb | 4 +++ app/views/snippets/_form.html.haml | 3 ++ app/views/snippets/_snippet.html.haml | 23 +++++++-------- app/views/snippets/show.html.haml | 40 +++++++++++++++------------ 5 files changed, 50 insertions(+), 29 deletions(-) diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb index 236b6c8c..cd7b0359 100644 --- a/app/helpers/snippets_helper.rb +++ b/app/helpers/snippets_helper.rb @@ -1,2 +1,11 @@ module SnippetsHelper + def snippet_lifetime_select_options + options = [ + ['forever', nil], + ['1 day', Date.strptime("#{Date.current.day}.#{Date.current.month}.#{Date.current.year}", "%d.%m.%Y") + 1.day], + ['1 week', Date.strptime("#{Date.current.day}.#{Date.current.month}.#{Date.current.year}", "%d.%m.%Y") + 1.week], + ['1 month', Date.strptime("#{Date.current.day}.#{Date.current.month}.#{Date.current.year}", "%d.%m.%Y") + 1.month] + ] + options_for_select(options) + end end diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 0f488a8c..acffc76c 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -33,6 +33,10 @@ class Snippet < ActiveRecord::Base def colorize system_colorize(content, file_name) end + + def expired? + expires_at && expires_at < Time.current + end end # == Schema Information # diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml index 7a34ae8e..2c9680c0 100644 --- a/app/views/snippets/_form.html.haml +++ b/app/views/snippets/_form.html.haml @@ -12,6 +12,9 @@ %tr %td= f.label :file_name %td= f.text_field :file_name, :placeholder => "example.rb" + %tr + %td= f.label "Lifetime" + %td= f.select :expires_at, snippet_lifetime_select_options %tr %td{:colspan => 2} = f.label :content, "Code" diff --git a/app/views/snippets/_snippet.html.haml b/app/views/snippets/_snippet.html.haml index 483ff42c..ddfba6bf 100644 --- a/app/views/snippets/_snippet.html.haml +++ b/app/views/snippets/_snippet.html.haml @@ -1,11 +1,12 @@ -%tr{ :id => dom_id(snippet), :class => "snippet", :url => project_snippet_path(@project, snippet) } - %td - = image_tag gravatar_icon(snippet.author.email), :class => "left", :width => 40, :style => "padding:0 5px;" - = truncate snippet.author.name, :lenght => 20 - %td= html_escape snippet.title - %td= html_escape snippet.file_name - %td - - if can?(current_user, :admin_snippet, @project) || snippet.author == current_user - = link_to 'Edit', edit_project_snippet_path(@project, snippet), :class => "lbutton positive" - - if can?(current_user, :admin_snippet, @project) || snippet.author == current_user - = link_to 'Destroy', [@project, snippet], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-snippet negative", :id => "destroy_snippet_#{snippet.id}" +- unless snippet.expired? + %tr{ :id => dom_id(snippet), :class => "snippet", :url => project_snippet_path(@project, snippet) } + %td + = image_tag gravatar_icon(snippet.author.email), :class => "left", :width => 40, :style => "padding:0 5px;" + = truncate snippet.author.name, :lenght => 20 + %td= html_escape snippet.title + %td= html_escape snippet.file_name + %td + - if can?(current_user, :admin_snippet, @project) || snippet.author == current_user + = link_to 'Edit', edit_project_snippet_path(@project, snippet), :class => "lbutton positive" + - if can?(current_user, :admin_snippet, @project) || snippet.author == current_user + = link_to 'Destroy', [@project, snippet], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-snippet negative", :id => "destroy_snippet_#{snippet.id}" diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index 899950b7..bfa1bf45 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -1,22 +1,26 @@ -%h2 - = "Snippet ##{@snippet.id} - #{@snippet.title}" +- if !@snippet.expired? + %h2 + = "Snippet ##{@snippet.id} - #{@snippet.title}" -.view_file - .view_file_header - %strong - = @snippet.file_name - %br/ - .view_file_content - :erb - <%= raw @snippet.colorize %> + .view_file + .view_file_header + %strong + = @snippet.file_name + %br/ + .view_file_content + :erb + <%= raw @snippet.colorize %> -- if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user - = link_to 'Edit', edit_project_snippet_path(@project, @snippet), :class => "lbutton positive" -- if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user - = link_to 'Destroy', [@project, @snippet], :confirm => 'Are you sure?', :method => :delete, :class => "lbutton delete-snippet negative", :id => "destroy_snippet_#{@snippet.id}" -.clear -%br -.snippet_notes= render "notes/notes" + - if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user + = link_to 'Edit', edit_project_snippet_path(@project, @snippet), :class => "lbutton positive" + - if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user + = link_to 'Destroy', [@project, @snippet], :confirm => 'Are you sure?', :method => :delete, :class => "lbutton delete-snippet negative", :id => "destroy_snippet_#{@snippet.id}" + .clear + %br + .snippet_notes= render "notes/notes" -.clear + .clear +- else + %h2 + Sorry, this snipped is no longer exists From de4e859928d22a44549ebb719bbfd669f630f1b1 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 11:50:14 +0500 Subject: [PATCH 113/176] install timecop for testing --- Gemfile | 3 ++- Gemfile.lock | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 28168095..2f3e870c 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ group :assets do gem 'uglifier' end -group :development do +group :development do gem 'rails-footnotes', '>= 3.7.5.rc4' gem 'annotate', :git => 'git://github.com/ctran/annotate_models.git' end @@ -42,6 +42,7 @@ group :development, :test do gem 'awesome_print' gem 'database_cleaner' gem 'launchy' + gem 'timecop' end diff --git a/Gemfile.lock b/Gemfile.lock index 01ec37e1..1f40f712 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -225,6 +225,7 @@ GEM rack (>= 1.0.0) thor (0.14.6) tilt (1.3.3) + timecop (0.3.5) treetop (1.4.10) polyglot polyglot (>= 0.3.1) @@ -276,6 +277,7 @@ DEPENDENCIES stamp therubyracer thin + timecop turn uglifier will_paginate (~> 3.0) From 5e584ee6264962cc60d9074c33141a28b4100607 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 12:11:42 +0500 Subject: [PATCH 114/176] refactor lifetime_select helper --- app/helpers/snippets_helper.rb | 8 ++++---- app/views/snippets/_form.html.haml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb index cd7b0359..6a91d616 100644 --- a/app/helpers/snippets_helper.rb +++ b/app/helpers/snippets_helper.rb @@ -1,10 +1,10 @@ module SnippetsHelper - def snippet_lifetime_select_options + def lifetime_select_options options = [ ['forever', nil], - ['1 day', Date.strptime("#{Date.current.day}.#{Date.current.month}.#{Date.current.year}", "%d.%m.%Y") + 1.day], - ['1 week', Date.strptime("#{Date.current.day}.#{Date.current.month}.#{Date.current.year}", "%d.%m.%Y") + 1.week], - ['1 month', Date.strptime("#{Date.current.day}.#{Date.current.month}.#{Date.current.year}", "%d.%m.%Y") + 1.month] + ['1 day', "#{Date.current + 1.day}"], + ['1 week', "#{Date.current + 1.week}"], + ['1 month', "#{Date.current + 1.month}"] ] options_for_select(options) end diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml index 2c9680c0..5cd0f74a 100644 --- a/app/views/snippets/_form.html.haml +++ b/app/views/snippets/_form.html.haml @@ -14,7 +14,7 @@ %td= f.text_field :file_name, :placeholder => "example.rb" %tr %td= f.label "Lifetime" - %td= f.select :expires_at, snippet_lifetime_select_options + %td= f.select :expires_at, lifetime_select_options %tr %td{:colspan => 2} = f.label :content, "Code" From 000c032482dbe2fe882f3b2583fe1a481edf460a Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 12:14:50 +0500 Subject: [PATCH 115/176] display recent snippets at top --- app/models/snippet.rb | 2 ++ app/views/snippets/index.html.haml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/snippet.rb b/app/models/snippet.rb index acffc76c..44cb8887 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -22,6 +22,8 @@ class Snippet < ActiveRecord::Base :presence => true, :length => { :within => 0..10000 } + scope :fresh, order("created_at DESC") + def self.content_types [ ".rb", ".py", ".pl", ".scala", ".c", ".cpp", ".java", diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml index fe5e6170..3f261000 100644 --- a/app/views/snippets/index.html.haml +++ b/app/views/snippets/index.html.haml @@ -8,7 +8,7 @@ %th Title %th File name %th - = render @snippets + = render @snippets.fresh :javascript $('.delete-snippet').live('ajax:success', function() { $(this).closest('tr').fadeOut(); }); From 325b84545ca09911df0bf80a7233b339aba755ed Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 13:12:12 +0500 Subject: [PATCH 116/176] don't count expired snippets --- app/models/snippet.rb | 1 + app/views/projects/_top_menu.html.haml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/snippet.rb b/app/models/snippet.rb index 44cb8887..b67db60b 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -23,6 +23,7 @@ class Snippet < ActiveRecord::Base :length => { :within => 0..10000 } scope :fresh, order("created_at DESC") + scope :non_expired, where(["expires_at IS NULL OR expires_at > ?", Time.current]) def self.content_types [ diff --git a/app/views/projects/_top_menu.html.haml b/app/views/projects/_top_menu.html.haml index 59f2533e..0b8751c9 100644 --- a/app/views/projects/_top_menu.html.haml +++ b/app/views/projects/_top_menu.html.haml @@ -23,7 +23,7 @@ = link_to project_snippets_path(@project), :class => (controller.controller_name == "snippets") ? "current" : nil do Snippets - if @project.snippets.count > 0 - %span{ :class => "top_menu_count" }= @project.snippets.count + %span{ :class => "top_menu_count" }= @project.snippets.non_expired.count - if @commit %span= link_to truncate(commit_name(@project,@commit), :length => 15), project_commit_path(@project, :id => @commit.id), :class => current_page?(:controller => "commits", :action => "show", :project_id => @project, :id => @commit.id) ? "current" : nil From 2801589c41c393bd9849c4b86c051a7ebfbfd7d7 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 14:47:06 +0500 Subject: [PATCH 117/176] remove jquery ui css from application layout. it's already included in assets --- app/views/layouts/application.html.haml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 3eb99da6..184307d0 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -7,7 +7,6 @@ = stylesheet_link_tag 'blueprint/print', :media => "print" = stylesheet_link_tag 'blueprint/plugins/buttons/screen', :media => "screen, projection" = stylesheet_link_tag 'blueprint/plugins/link-icons/screen', :media => "screen, projection" - = stylesheet_link_tag 'jquery_ui/jquery-ui-1.8.16.custom', :media => "screen, projection" = stylesheet_link_tag "application" = javascript_include_tag "application" = csrf_meta_tags From be364d1004ca80f94d9203b25eca285a623758af Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 14:47:56 +0500 Subject: [PATCH 118/176] move jquery ui images to vendor directory --- .../jquery-ui}/ui-bg_flat_0_aaaaaa_40x100.png | Bin .../ui-bg_flat_75_ffffff_40x100.png | Bin .../ui-bg_glass_55_fbf9ee_1x400.png | Bin .../ui-bg_glass_65_ffffff_1x400.png | Bin .../ui-bg_glass_75_dadada_1x400.png | Bin .../ui-bg_glass_75_e6e6e6_1x400.png | Bin .../ui-bg_glass_95_fef1ec_1x400.png | Bin .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin .../jquery-ui}/ui-icons_222222_256x240.png | Bin .../jquery-ui}/ui-icons_2e83ff_256x240.png | Bin .../jquery-ui}/ui-icons_454545_256x240.png | Bin .../jquery-ui}/ui-icons_888888_256x240.png | Bin .../jquery-ui}/ui-icons_cd0a0a_256x240.png | Bin .../stylesheets/jquery-ui/jquery-ui.css | 32 +++++++++--------- 14 files changed, 16 insertions(+), 16 deletions(-) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-bg_flat_0_aaaaaa_40x100.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-bg_flat_75_ffffff_40x100.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-bg_glass_55_fbf9ee_1x400.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-bg_glass_65_ffffff_1x400.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-bg_glass_75_dadada_1x400.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-bg_glass_75_e6e6e6_1x400.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-bg_glass_95_fef1ec_1x400.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-bg_highlight-soft_75_cccccc_1x100.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-icons_222222_256x240.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-icons_2e83ff_256x240.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-icons_454545_256x240.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-icons_888888_256x240.png (100%) rename {app/assets/images/jquery_ui/images => vendor/assets/images/jquery-ui}/ui-icons_cd0a0a_256x240.png (100%) diff --git a/app/assets/images/jquery_ui/images/ui-bg_flat_0_aaaaaa_40x100.png b/vendor/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-bg_flat_0_aaaaaa_40x100.png rename to vendor/assets/images/jquery-ui/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/app/assets/images/jquery_ui/images/ui-bg_flat_75_ffffff_40x100.png b/vendor/assets/images/jquery-ui/ui-bg_flat_75_ffffff_40x100.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-bg_flat_75_ffffff_40x100.png rename to vendor/assets/images/jquery-ui/ui-bg_flat_75_ffffff_40x100.png diff --git a/app/assets/images/jquery_ui/images/ui-bg_glass_55_fbf9ee_1x400.png b/vendor/assets/images/jquery-ui/ui-bg_glass_55_fbf9ee_1x400.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-bg_glass_55_fbf9ee_1x400.png rename to vendor/assets/images/jquery-ui/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/app/assets/images/jquery_ui/images/ui-bg_glass_65_ffffff_1x400.png b/vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-bg_glass_65_ffffff_1x400.png rename to vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png diff --git a/app/assets/images/jquery_ui/images/ui-bg_glass_75_dadada_1x400.png b/vendor/assets/images/jquery-ui/ui-bg_glass_75_dadada_1x400.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-bg_glass_75_dadada_1x400.png rename to vendor/assets/images/jquery-ui/ui-bg_glass_75_dadada_1x400.png diff --git a/app/assets/images/jquery_ui/images/ui-bg_glass_75_e6e6e6_1x400.png b/vendor/assets/images/jquery-ui/ui-bg_glass_75_e6e6e6_1x400.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-bg_glass_75_e6e6e6_1x400.png rename to vendor/assets/images/jquery-ui/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/app/assets/images/jquery_ui/images/ui-bg_glass_95_fef1ec_1x400.png b/vendor/assets/images/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-bg_glass_95_fef1ec_1x400.png rename to vendor/assets/images/jquery-ui/ui-bg_glass_95_fef1ec_1x400.png diff --git a/app/assets/images/jquery_ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_cccccc_1x100.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-bg_highlight-soft_75_cccccc_1x100.png rename to vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/app/assets/images/jquery_ui/images/ui-icons_222222_256x240.png b/vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-icons_222222_256x240.png rename to vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png diff --git a/app/assets/images/jquery_ui/images/ui-icons_2e83ff_256x240.png b/vendor/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-icons_2e83ff_256x240.png rename to vendor/assets/images/jquery-ui/ui-icons_2e83ff_256x240.png diff --git a/app/assets/images/jquery_ui/images/ui-icons_454545_256x240.png b/vendor/assets/images/jquery-ui/ui-icons_454545_256x240.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-icons_454545_256x240.png rename to vendor/assets/images/jquery-ui/ui-icons_454545_256x240.png diff --git a/app/assets/images/jquery_ui/images/ui-icons_888888_256x240.png b/vendor/assets/images/jquery-ui/ui-icons_888888_256x240.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-icons_888888_256x240.png rename to vendor/assets/images/jquery-ui/ui-icons_888888_256x240.png diff --git a/app/assets/images/jquery_ui/images/ui-icons_cd0a0a_256x240.png b/vendor/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png similarity index 100% rename from app/assets/images/jquery_ui/images/ui-icons_cd0a0a_256x240.png rename to vendor/assets/images/jquery-ui/ui-icons_cd0a0a_256x240.png diff --git a/vendor/assets/stylesheets/jquery-ui/jquery-ui.css b/vendor/assets/stylesheets/jquery-ui/jquery-ui.css index 4308e08e..0cd7af67 100644 --- a/vendor/assets/stylesheets/jquery-ui/jquery-ui.css +++ b/vendor/assets/stylesheets/jquery-ui/jquery-ui.css @@ -59,26 +59,26 @@ .ui-widget { font-family: "Helvetica Neue",Arial,Helvetica,sans-serif; font-size: 1.1em; } .ui-widget .ui-widget { font-size: 1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } -.ui-widget-content { border: 1px solid #dddddd; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content { border: 1px solid #dddddd; background: #ffffff url(ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } .ui-widget-content a { color: #222222; } .ui-widget-header { color: #222222; font-weight: bold; } .ui-widget-header a { color: #222222; } /* Interaction states ----------------------------------*/ -.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } -.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } -.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } .ui-widget :active { outline: none; } /* Interaction Cues ----------------------------------*/ -.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } -.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } @@ -89,14 +89,14 @@ ----------------------------------*/ /* states and images */ -.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } -.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } -.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } -.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } -.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } -.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } -.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } -.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } +.ui-icon { width: 16px; height: 16px; background-image: url(ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(ui-icons_cd0a0a_256x240.png); } /* positioning */ .ui-icon-carat-1-n { background-position: 0 0; } @@ -286,8 +286,8 @@ /*.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }*/ /* Overlays */ -.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } -.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* +.ui-widget-overlay { background: #aaaaaa url(ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* * jQuery UI Resizable 1.8.16 * * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) From 2db09ada72d7c27e494c73da35f09915659a24cd Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 16:14:46 +0500 Subject: [PATCH 119/176] extend assets path with jquery-ui images, so rails can find them --- config/application.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config/application.rb b/config/application.rb index 9a4fd4e4..3481c6d6 100644 --- a/config/application.rb +++ b/config/application.rb @@ -44,5 +44,8 @@ module Gitlab # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0' + + # Extend assets path + config.assets.paths << Rails.root.join('vendor', 'assets', 'images', 'jquery-ui') end end From d64f23e29419c92c36a0f64917563336ed6012e3 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 27 Oct 2011 16:44:29 +0300 Subject: [PATCH 120/176] code cleaning --- Gemfile | 3 +- Gemfile.lock | 2 - app/controllers/admin/projects_controller.rb | 44 ++++--------------- .../admin/team_members_controller.rb | 44 ++++--------------- app/controllers/admin/users_controller.rb | 15 ------- 5 files changed, 19 insertions(+), 89 deletions(-) diff --git a/Gemfile b/Gemfile index 77a00659..46320d22 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,7 @@ gem 'rails', '3.1.0' gem 'sqlite3' gem 'devise', "1.4.7" gem 'stamp' -gem 'will_paginate', '~> 3.0' +gem 'kaminari' gem 'haml-rails' gem 'jquery-rails' gem 'grit', :git => 'git://github.com/gitlabhq/grit.git' @@ -16,7 +16,6 @@ gem 'faker' gem 'seed-fu', :git => 'git://github.com/mbleigh/seed-fu.git' gem "inifile" gem "pygments.rb", "0.2.3" -gem "kaminari" gem "thin" gem "git" gem "acts_as_list" diff --git a/Gemfile.lock b/Gemfile.lock index 5ba34459..44faaad7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -232,7 +232,6 @@ GEM multi_json (>= 1.0.2) warden (1.0.5) rack (>= 1.0) - will_paginate (3.0.0) xpath (0.1.4) nokogiri (~> 1.3) @@ -274,4 +273,3 @@ DEPENDENCIES thin turn uglifier - will_paginate (~> 3.0) diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 55752619..a7113639 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -4,29 +4,14 @@ class Admin::ProjectsController < ApplicationController def index @admin_projects = Project.page(params[:page]) - - respond_to do |format| - format.html # index.html.erb - format.json { render json: @admin_projects } - end end def show @admin_project = Project.find_by_code(params[:id]) - - respond_to do |format| - format.html # show.html.erb - format.json { render json: @admin_project } - end end def new @admin_project = Project.new - - respond_to do |format| - format.html # new.html.erb - format.json { render json: @admin_project } - end end def edit @@ -37,28 +22,20 @@ class Admin::ProjectsController < ApplicationController @admin_project = Project.new(params[:project]) @admin_project.owner = current_user - respond_to do |format| - if @admin_project.save - format.html { redirect_to [:admin, @admin_project], notice: 'Project was successfully created.' } - format.json { render json: @admin_project, status: :created, location: @admin_project } - else - format.html { render action: "new" } - format.json { render json: @admin_project.errors, status: :unprocessable_entity } - end + if @admin_project.save + redirect_to [:admin, @admin_project], notice: 'Project was successfully created.' + else + render :action => "new" end end def update @admin_project = Project.find_by_code(params[:id]) - respond_to do |format| - if @admin_project.update_attributes(params[:project]) - format.html { redirect_to [:admin, @admin_project], notice: 'Project was successfully updated.' } - format.json { head :ok } - else - format.html { render action: "edit" } - format.json { render json: @admin_project.errors, status: :unprocessable_entity } - end + if @admin_project.update_attributes(params[:project]) + redirect_to [:admin, @admin_project], notice: 'Project was successfully updated.' + else + render :action => "edit" end end @@ -66,9 +43,6 @@ class Admin::ProjectsController < ApplicationController @admin_project = Project.find_by_code(params[:id]) @admin_project.destroy - respond_to do |format| - format.html { redirect_to admin_projects_url } - format.json { head :ok } - end + redirect_to admin_projects_url end end diff --git a/app/controllers/admin/team_members_controller.rb b/app/controllers/admin/team_members_controller.rb index bca9bfeb..8ae32bc6 100644 --- a/app/controllers/admin/team_members_controller.rb +++ b/app/controllers/admin/team_members_controller.rb @@ -4,29 +4,14 @@ class Admin::TeamMembersController < ApplicationController def index @admin_team_members = UsersProject.page(params[:page]).per(100).order("project_id DESC") - - respond_to do |format| - format.html # index.html.erb - format.json { render json: @admin_team_members } - end end def show @admin_team_member = UsersProject.find(params[:id]) - - respond_to do |format| - format.html # show.html.erb - format.json { render json: @admin_team_member } - end end def new @admin_team_member = UsersProject.new(params[:team_member]) - - respond_to do |format| - format.html # new.html.erb - format.json { render json: @admin_team_member } - end end def edit @@ -37,14 +22,10 @@ class Admin::TeamMembersController < ApplicationController @admin_team_member = UsersProject.new(params[:team_member]) @admin_team_member.project_id = params[:team_member][:project_id] - respond_to do |format| - if @admin_team_member.save - format.html { redirect_to admin_team_member_path(@admin_team_member), notice: 'UsersProject was successfully created.' } - format.json { render json: @admin_team_member, status: :created, location: @team_member } - else - format.html { render action: "new" } - format.json { render json: @admin_team_member.errors, status: :unprocessable_entity } - end + if @admin_team_member.save + redirect_to admin_team_member_path(@admin_team_member), notice: 'UsersProject was successfully created.' + else + render action: "new" end end @@ -52,14 +33,10 @@ class Admin::TeamMembersController < ApplicationController @admin_team_member = UsersProject.find(params[:id]) @admin_team_member.project_id = params[:team_member][:project_id] - respond_to do |format| - if @admin_team_member.update_attributes(params[:team_member]) - format.html { redirect_to admin_team_member_path(@admin_team_member), notice: 'UsersProject was successfully updated.' } - format.json { head :ok } - else - format.html { render action: "edit" } - format.json { render json: @admin_team_member.errors, status: :unprocessable_entity } - end + if @admin_team_member.update_attributes(params[:team_member]) + redirect_to admin_team_member_path(@admin_team_member), notice: 'UsersProject was successfully updated.' + else + render action: "edit" end end @@ -67,9 +44,6 @@ class Admin::TeamMembersController < ApplicationController @admin_team_member = UsersProject.find(params[:id]) @admin_team_member.destroy - respond_to do |format| - format.html { redirect_to admin_team_members_url } - format.json { head :ok } - end + redirect_to admin_team_members_url end end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index e9ad1e55..f6304e15 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -4,29 +4,14 @@ class Admin::UsersController < ApplicationController def index @admin_users = User.page(params[:page]) - - respond_to do |format| - format.html # index.html.erb - format.json { render json: @admin_users } - end end def show @admin_user = User.find(params[:id]) - - respond_to do |format| - format.html # show.html.erb - format.json { render json: @admin_user } - end end def new @admin_user = User.new(:projects_limit => 10) - - respond_to do |format| - format.html # new.html.erb - format.json { render json: @admin_user } - end end def edit From e41bc4dd508666fd8e019a4dc12825e23128a00b Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 27 Oct 2011 16:50:35 +0300 Subject: [PATCH 121/176] #173 --- app/views/commits/_text_file.html.haml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml index db71c387..1ef4a3c8 100644 --- a/app/views/commits/_text_file.html.haml +++ b/app/views/commits/_text_file.html.haml @@ -2,6 +2,7 @@ - line_new = 0 - lines_arr = diff.diff.lines.to_a - lines_arr.each do |line| + - next if line.match(/^--- \/dev\/null/) - next if line.match(/^--- a/) - next if line.match(/^\+\+\+ b/) - if line.match(/^@@ -/) From 5fe736ab2847a5fd7f85363197e3ae0cbfd959e1 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 27 Oct 2011 17:08:40 +0300 Subject: [PATCH 122/176] little fix --- app/views/issues/_show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml index afcd2b6e..ebcaae29 100644 --- a/app/views/issues/_show.html.haml +++ b/app/views/issues/_show.html.haml @@ -1,5 +1,5 @@ %tr{ :id => dom_id(issue), :class => "issue #{issue.critical ? "critical" : ""}", :url => project_issue_path(@project, issue) } - - if can?(current_user, :admin_issue, @project) && !params[:f] || params[:f] == "0" + - if can?(current_user, :admin_issue, @project) && (!params[:f] || params[:f] == "0") %td = image_tag "move.png" , :class => [:handle, :left] %td From 9611a27e0ca7e800d978d7355dbfb896f6f6cd2c Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 27 Oct 2011 17:33:20 +0300 Subject: [PATCH 123/176] note as text --- app/models/note.rb | 2 +- app/views/notes/_form.html.haml | 2 +- db/migrate/20111027142641_change_note_note_to_text.rb | 8 ++++++++ db/schema.rb | 4 ++-- 4 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 db/migrate/20111027142641_change_note_note_to_text.rb diff --git a/app/models/note.rb b/app/models/note.rb index 9dcdbb55..645bc7ce 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -13,7 +13,7 @@ class Note < ActiveRecord::Base validates :note, :presence => true, - :length => { :within => 0..255 } + :length => { :within => 0..5000 } validates :attachment, :file_size => { diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index 14e74fa6..86f0b779 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -10,7 +10,7 @@ %div = f.label :note - %cite (255 symbols only) + %cite %br = f.text_area :note, :size => 255 diff --git a/db/migrate/20111027142641_change_note_note_to_text.rb b/db/migrate/20111027142641_change_note_note_to_text.rb new file mode 100644 index 00000000..d762d361 --- /dev/null +++ b/db/migrate/20111027142641_change_note_note_to_text.rb @@ -0,0 +1,8 @@ +class ChangeNoteNoteToText < ActiveRecord::Migration + def up + change_column :notes, :note, :text + end + + def down + end +end diff --git a/db/schema.rb b/db/schema.rb index 21c224d4..8dd75e75 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111025134235) do +ActiveRecord::Schema.define(:version => 20111027142641) do create_table "issues", :force => true do |t| t.string "title" @@ -36,7 +36,7 @@ ActiveRecord::Schema.define(:version => 20111025134235) do end create_table "notes", :force => true do |t| - t.string "note" + t.text "note", :limit => 255 t.string "noteable_id" t.string "noteable_type" t.integer "author_id" From f4e7ad7a4b8f188419104995e7b6346149ab31ab Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 27 Oct 2011 17:41:10 +0300 Subject: [PATCH 124/176] fixed limit --- db/migrate/20111027142641_change_note_note_to_text.rb | 2 +- db/schema.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/migrate/20111027142641_change_note_note_to_text.rb b/db/migrate/20111027142641_change_note_note_to_text.rb index d762d361..1bcf4b72 100644 --- a/db/migrate/20111027142641_change_note_note_to_text.rb +++ b/db/migrate/20111027142641_change_note_note_to_text.rb @@ -1,6 +1,6 @@ class ChangeNoteNoteToText < ActiveRecord::Migration def up - change_column :notes, :note, :text + change_column :notes, :note, :text, :limit => false end def down diff --git a/db/schema.rb b/db/schema.rb index 8dd75e75..9c99e532 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -36,7 +36,7 @@ ActiveRecord::Schema.define(:version => 20111027142641) do end create_table "notes", :force => true do |t| - t.text "note", :limit => 255 + t.text "note" t.string "noteable_id" t.string "noteable_type" t.integer "author_id" From 2258db66c2e8ddccc1716b92f9d9a3a1cb3eff7f Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 27 Oct 2011 18:18:50 +0300 Subject: [PATCH 125/176] issue can be edit from show page --- app/views/issues/index.html.haml | 2 +- app/views/issues/show.html.haml | 9 +++++++++ app/views/issues/update.js.haml | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml index 56042fa2..a70c65d4 100644 --- a/app/views/issues/index.html.haml +++ b/app/views/issues/index.html.haml @@ -45,7 +45,7 @@ }); $('.delete-issue').live('ajax:success', function() { - $(this).closest('tr').fadeOut(); }); + $(this).closest('tr').fadeOut(); updatePage();}); function setSortable(){ $('#issues-table>tbody').sortable({ diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 29b6f3f7..58bebe9b 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -3,6 +3,10 @@ .span-15 = simple_format html_escape(@issue.content) + + + .clear + %br .issue_notes= render "notes/notes" .span-8.right .span-8 @@ -39,5 +43,10 @@ - else = check_box_tag "closed", 1, @issue.closed, :disabled => true + + - if can?(current_user, :admin_issue, @issue) + .clear + = link_to 'Edit', edit_project_issue_path(@project, @issue), :class => "lbutton positive", :remote => true + .right= link_to 'Destroy', [@project, @issue], :confirm => 'Are you sure?', :method => :delete, :class => "lbutton delete-issue negative", :id => "destroy_issue_#{@issue.id}" .clear diff --git a/app/views/issues/update.js.haml b/app/views/issues/update.js.haml index 30fca38c..137dba3c 100644 --- a/app/views/issues/update.js.haml +++ b/app/views/issues/update.js.haml @@ -6,7 +6,7 @@ - if @issue.valid? :plain $("#edit_issue_dialog").dialog("close"); - $.ajax({type: "GET", url: location.href, dataType: "script"}); + updatePage(); - else :plain $("#edit_issue_dialog").empty(); From 56d9761844b2665e9e48d50f15f7ac3a63d60618 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 27 Oct 2011 18:46:30 +0300 Subject: [PATCH 126/176] moving out of body --- app/models/issue.rb | 6 +++--- app/views/issues/_form.html.haml | 8 ++++---- app/views/issues/_show.html.haml | 2 +- app/views/issues/show.html.haml | 8 ++------ db/migrate/20111027152724_issue_conten_to_note.rb | 11 +++++++++++ 5 files changed, 21 insertions(+), 14 deletions(-) create mode 100644 db/migrate/20111027152724_issue_conten_to_note.rb diff --git a/app/models/issue.rb b/app/models/issue.rb index ca1c5eaf..9fb7ef30 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -14,9 +14,9 @@ class Issue < ActiveRecord::Base :presence => true, :length => { :within => 0..255 } - validates :content, - :presence => true, - :length => { :within => 0..2000 } + #validates :content, + #:presence => true, + #:length => { :within => 0..2000 } scope :critical, where(:critical => true) scope :non_critical, where(:critical => false) diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml index eae0ee0f..80f19d62 100644 --- a/app/views/issues/_form.html.haml +++ b/app/views/issues/_form.html.haml @@ -7,10 +7,10 @@ .span-8 = f.label :title - = f.text_field :title, :style => "width:450px" - .span-8 - = f.label :content - = f.text_area :content, :style => "width:450px; height:130px" + = f.text_area :title, :style => "width:450px; height:100px", :maxlength => 255 + -#.span-8 + -#= f.label :content + -#= f.text_area :content, :style => "width:450px; height:130px" .span-8.append-bottom = f.label :assignee_id = f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }) diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml index ebcaae29..9cce2871 100644 --- a/app/views/issues/_show.html.haml +++ b/app/views/issues/_show.html.haml @@ -7,7 +7,7 @@ = truncate issue.assignee.name, :lenght => 20 %td ##{issue.id} %td - = html_escape issue.title + = truncate(html_escape(issue.title), :length => 50) %br - if issue.critical %span.tag.high critical diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 58bebe9b..eb972d33 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -1,12 +1,8 @@ %h2 - = "Issue ##{@issue.id} - #{@issue.title}" + = "Issue ##{@issue.id} - #{truncate @issue.title, :length => 50}" .span-15 - = simple_format html_escape(@issue.content) - - - .clear - %br + -#= simple_format html_escape(@issue.content) .issue_notes= render "notes/notes" .span-8.right .span-8 diff --git a/db/migrate/20111027152724_issue_conten_to_note.rb b/db/migrate/20111027152724_issue_conten_to_note.rb new file mode 100644 index 00000000..15d96c30 --- /dev/null +++ b/db/migrate/20111027152724_issue_conten_to_note.rb @@ -0,0 +1,11 @@ +class IssueContenToNote < ActiveRecord::Migration + def up + raise "Not ready" + Issue.find_each(:batch_size => 100) do |issue| + + end + end + + def down + end +end From 01f72bfa83ef05817c2e9898a62ae09919a6d505 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Thu, 27 Oct 2011 23:35:16 +0500 Subject: [PATCH 127/176] Revert "install timecop for testing" This reverts commit 0aa5682f8e3d2f50443fa8ac457daf5c9784dfd8. --- Gemfile | 3 +-- Gemfile.lock | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 2f3e870c..28168095 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ group :assets do gem 'uglifier' end -group :development do +group :development do gem 'rails-footnotes', '>= 3.7.5.rc4' gem 'annotate', :git => 'git://github.com/ctran/annotate_models.git' end @@ -42,7 +42,6 @@ group :development, :test do gem 'awesome_print' gem 'database_cleaner' gem 'launchy' - gem 'timecop' end diff --git a/Gemfile.lock b/Gemfile.lock index 1f40f712..01ec37e1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -225,7 +225,6 @@ GEM rack (>= 1.0.0) thor (0.14.6) tilt (1.3.3) - timecop (0.3.5) treetop (1.4.10) polyglot polyglot (>= 0.3.1) @@ -277,7 +276,6 @@ DEPENDENCIES stamp therubyracer thin - timecop turn uglifier will_paginate (~> 3.0) From b6cdd1c819b4a43cd00dfdc9dbffc1490593a8b5 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Fri, 28 Oct 2011 00:25:50 +0500 Subject: [PATCH 128/176] test expired snippets --- app/models/snippet.rb | 1 + app/views/snippets/show.html.haml | 2 +- spec/models/snippet_spec.rb | 1 + spec/requests/snippets_spec.rb | 8 ++++++++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/models/snippet.rb b/app/models/snippet.rb index b67db60b..5c61cf1c 100644 --- a/app/models/snippet.rb +++ b/app/models/snippet.rb @@ -53,5 +53,6 @@ end # created_at :datetime # updated_at :datetime # file_name :string(255) +# expires_at :datetime # diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index bfa1bf45..757cdb11 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -23,4 +23,4 @@ - else %h2 - Sorry, this snipped is no longer exists + Sorry, this snippet is no longer exists diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index 9dab72ca..037287a9 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -26,5 +26,6 @@ end # created_at :datetime # updated_at :datetime # file_name :string(255) +# expires_at :datetime # diff --git a/spec/requests/snippets_spec.rb b/spec/requests/snippets_spec.rb index d4811958..ee4f90e6 100644 --- a/spec/requests/snippets_spec.rb +++ b/spec/requests/snippets_spec.rb @@ -23,6 +23,14 @@ describe "Snippets" do it { should have_content(@snippet.project.name) } it { should have_content(@snippet.author.name) } + it "doesn't show expired snippets" do + @snippet.update_attribute(:expires_at, 1.day.ago.to_time) + visit project_snippet_path(project, @snippet) + page.should have_content("Sorry, this snippet is no longer exists") + page.should_not have_content(@snippet.title) + page.should_not have_content(@snippet.content) + end + describe "Destroy" do before do # admin access to remove snippet From e92669fb2d60e4bb331e67d9bfd17a5266152a65 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Fri, 28 Oct 2011 00:37:17 +0500 Subject: [PATCH 129/176] install rdiscount --- Gemfile | 3 ++- Gemfile.lock | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 60fc118c..fc040ce0 100644 --- a/Gemfile +++ b/Gemfile @@ -19,6 +19,7 @@ gem "pygments.rb", "0.2.3" gem "thin" gem "git" gem "acts_as_list" +gem 'rdiscount' group :assets do gem 'sass-rails', " ~> 3.1.0" @@ -26,7 +27,7 @@ group :assets do gem 'uglifier' end -group :development do +group :development do gem 'rails-footnotes', '>= 3.7.5.rc4' gem 'annotate', :git => 'git://github.com/ctran/annotate_models.git' end diff --git a/Gemfile.lock b/Gemfile.lock index 83ccebd8..83df35b5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -161,6 +161,7 @@ GEM rdoc (~> 3.4) thor (~> 0.14.6) rake (0.9.2) + rdiscount (1.6.8) rdoc (3.9.4) rspec (2.6.0) rspec-core (~> 2.6.0) @@ -264,6 +265,7 @@ DEPENDENCIES pygments.rb (= 0.2.3) rails (= 3.1.0) rails-footnotes (>= 3.7.5.rc4) + rdiscount rspec-rails ruby-debug19 sass-rails (~> 3.1.0) From 6c7706eb17cff08ba0c3cccc3ebcfc969ae0f6e3 Mon Sep 17 00:00:00 2001 From: Nihad Abbasov Date: Fri, 28 Oct 2011 00:57:10 +0500 Subject: [PATCH 130/176] process notes w/ rdiscount --- app/views/notes/_show.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_show.html.haml index ee9f9ffa..1907e9cc 100644 --- a/app/views/notes/_show.html.haml +++ b/app/views/notes/_show.html.haml @@ -2,7 +2,7 @@ %div.note_author = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" %div.note_content.left - = simple_format(html_escape(note.note)) + = raw RDiscount.new(note.note, :smart, :filter_html).to_html - if note.attachment.url Attachment: = link_to note.attachment_identifier, note.attachment.url, :target => "_blank" From a0171813391c8226802621a710798e376fea2f1e Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 28 Oct 2011 12:22:09 +0300 Subject: [PATCH 131/176] new issue format --- app/assets/stylesheets/projects.css.scss | 4 +++ app/controllers/issues_controller.rb | 2 +- app/views/issues/_show.html.haml | 2 +- app/views/issues/show.html.haml | 13 +++++++-- .../20111027152724_issue_conten_to_note.rb | 27 +++++++++++++++++-- db/schema.rb | 2 +- spec/factories.rb | 1 - spec/requests/issues_spec.rb | 19 +++++++++++-- 8 files changed, 60 insertions(+), 10 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index f9c7592b..bde9aa5d 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -662,6 +662,10 @@ tbody tr:nth-child(2n) td, tbody tr.even td { background: #4466cc; color:white; } + &.normal { + background: #2c5ca6; + color:white; + } &.notes { background: #2c5c66; color:white; diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 26e4a573..d0fad8ed 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -34,7 +34,7 @@ class IssuesController < ApplicationController end def show - @notes = @issue.notes + @notes = @issue.notes.order("created_at ASC") @note = @project.notes.new(:noteable => @issue) end diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml index 9cce2871..94cc03d1 100644 --- a/app/views/issues/_show.html.haml +++ b/app/views/issues/_show.html.haml @@ -7,7 +7,7 @@ = truncate issue.assignee.name, :lenght => 20 %td ##{issue.id} %td - = truncate(html_escape(issue.title), :length => 50) + = truncate(html_escape(issue.title), :length => 60) %br - if issue.critical %span.tag.high critical diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index eb972d33..c6105283 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -1,6 +1,5 @@ %h2 - = "Issue ##{@issue.id} - #{truncate @issue.title, :length => 50}" - + = "Issue ##{@issue.id} - #{html_escape(@issue.title)}" .span-15 -#= simple_format html_escape(@issue.content) .issue_notes= render "notes/notes" @@ -29,6 +28,16 @@ %td = image_tag gravatar_icon(@issue.assignee.email), :class => "left", :width => 40, :style => "padding:0 5px;" = @issue.assignee.name + %tr + %td Tags + %td + - if @issue.critical + %span.tag.high critical + - else + %span.tag.normal normal + + - if @issue.today? + %span.tag.today today %tr %td Closed? %td diff --git a/db/migrate/20111027152724_issue_conten_to_note.rb b/db/migrate/20111027152724_issue_conten_to_note.rb index 15d96c30..c151a931 100644 --- a/db/migrate/20111027152724_issue_conten_to_note.rb +++ b/db/migrate/20111027152724_issue_conten_to_note.rb @@ -1,8 +1,31 @@ class IssueContenToNote < ActiveRecord::Migration def up - raise "Not ready" + puts "Issue content is deprecated -> move to notes" Issue.find_each(:batch_size => 100) do |issue| - + next if issue.content.blank? + note = Note.new( + :note => issue.content, + :project_id => issue.project_id, + :noteable => issue, + :created_at => issue.created_at, + :updated_at => issue.created_at + ) + note.author_id = issue.author_id + + if note.save + issue.update_attributes(:content => nil) + print "." + else + print "F" + end + end + + total = Issue.where("content is not null").count + + if total > 0 + puts "content of #{total} issues were not migrated" + else + puts "Done" end end diff --git a/db/schema.rb b/db/schema.rb index 9c99e532..e4f7379c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111027142641) do +ActiveRecord::Schema.define(:version => 20111027152724) do create_table "issues", :force => true do |t| t.string "title" diff --git a/spec/factories.rb b/spec/factories.rb index cc0cd4e5..36aa4fc9 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -32,7 +32,6 @@ end Factory.add(:issue, Issue) do |obj| obj.title = Faker::Lorem.sentence - obj.content = Faker::Lorem.sentences end Factory.add(:snippet, Snippet) do |obj| diff --git a/spec/requests/issues_spec.rb b/spec/requests/issues_spec.rb index 184f8293..b13e43ad 100644 --- a/spec/requests/issues_spec.rb +++ b/spec/requests/issues_spec.rb @@ -80,7 +80,6 @@ describe "Issues" do describe "fill in" do before do fill_in "issue_title", :with => "bug 345" - fill_in "issue_content", :with => "app bug 345" click_link "Select user" click_link @user.name end @@ -112,6 +111,23 @@ describe "Issues" do end end + describe "Show issue" do + before do + @issue = Factory :issue, + :author => @user, + :assignee => @user, + :project => project + + visit project_issue_path(project, @issue) + end + + it "should have valid show page for issue" do + page.should have_content @issue.title + page.should have_content @user.name + page.should have_content "today" + end + end + describe "Edit issue", :js => true do before do @issue = Factory :issue, @@ -129,7 +145,6 @@ describe "Issues" do describe "fill in" do before do fill_in "issue_title", :with => "bug 345" - fill_in "issue_content", :with => "app bug 345" end it { expect { click_button "Save" }.to_not change {Issue.count} } From 1ffb4b98c0405ee4c8bafaf9b67f1fc49493fbbc Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 28 Oct 2011 14:41:39 +0300 Subject: [PATCH 132/176] new design/layout started. projects page --- app/assets/images/.directory | 2 +- app/assets/images/bg-header.png | Bin 0 -> 212 bytes app/assets/images/images.png | Bin 0 -> 6472 bytes app/assets/images/login-logo.png | Bin 0 -> 1429 bytes app/assets/javascripts/modernizr-2.0.6.min.js | 4 + app/assets/stylesheets/projects.css.scss | 6 +- app/assets/stylesheets/style.scss | 521 ++++++++++++++++++ app/views/layouts/_head_panel.html.erb | 39 +- app/views/layouts/_page_title.html.haml | 6 + app/views/layouts/application.html.haml | 34 +- app/views/projects/_tile.html.haml | 29 +- app/views/projects/index.html.haml | 7 + 12 files changed, 605 insertions(+), 43 deletions(-) create mode 100644 app/assets/images/bg-header.png create mode 100644 app/assets/images/images.png create mode 100644 app/assets/images/login-logo.png create mode 100755 app/assets/javascripts/modernizr-2.0.6.min.js create mode 100755 app/assets/stylesheets/style.scss create mode 100644 app/views/layouts/_page_title.html.haml diff --git a/app/assets/images/.directory b/app/assets/images/.directory index 93a51f7c..d6f1a908 100644 --- a/app/assets/images/.directory +++ b/app/assets/images/.directory @@ -1,4 +1,4 @@ [Dolphin] ShowPreview=true -Timestamp=2011,9,14,20,34,18 +Timestamp=2011,10,28,13,16,25 Version=2 diff --git a/app/assets/images/bg-header.png b/app/assets/images/bg-header.png new file mode 100644 index 0000000000000000000000000000000000000000..8759ca589fccdfcddd6ec42ba4474257da26c855 GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^j6lrJ!VDy>ldP5lDdu7)&kzm{j@u9Y9{{=h0X`wF z{=sq9j^1WAu7+lII))av=1#N#N^ur=L>4nJa0`JjznHv8d^+P v(F&6Hba4#fn3r6IT literal 0 HcmV?d00001 diff --git a/app/assets/images/images.png b/app/assets/images/images.png new file mode 100644 index 0000000000000000000000000000000000000000..8af7472e70e1030ccb44952f287964cf460cbe20 GIT binary patch literal 6472 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",a,""].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},w=function(b){if(a.matchMedia)return matchMedia(b).matches;var c;v("@media "+b+" { #"+i+" { position: absolute; } }",function(b){c=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position=="absolute"});return c},x=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=D(e[d],"function"),D(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),y,z={}.hasOwnProperty,A;!D(z,c)&&!D(z.call,c)?A=function(a,b){return z.call(a,b)}:A=function(a,b){return b in a&&D(a.constructor.prototype[b],c)};var H=function(c,d){var f=c.join(""),g=d.length;v(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||j.touch.offsetTop===9,e.csstransforms3d=j.csstransforms3d.offsetLeft===9,e.generatedcontent=j.generatedcontent.offsetHeight>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",o.join("touch-enabled),("),i,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",o.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join(""),['#generatedcontent:after{content:"',m,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!D(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){return x("dragstart")&&x("drop")},r.websockets=function(){for(var b=-1,c=p.length;++b";return(a.firstChild&&a.firstChild.namespaceURI)==q.svg},r.smil=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"animate")))},r.svgclippaths=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"clipPath")))};for(var J in r)A(r,J)&&(y=J.toLowerCase(),e[y]=r[J](),u.push((e[y]?"":"no-")+y));e.input||I(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)A(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return;b=typeof b=="boolean"?b:!!b(),g.className+=" "+(b?"":"no-")+a,e[a]=b}return e},B(""),j=l=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b=u.minw)&&(!u.maxw||u.maxw&&l<=u.maxw))m[u.media]||(m[u.media]=[]),m[u.media].push(f[u.rules])}for(var t in g)g[t]&&g[t].parentNode===j&&j.removeChild(g[t]);for(var t in m){var v=c.createElement("style"),w=m[t].join("\n");v.type="text/css",v.media=t,v.styleSheet?v.styleSheet.cssText=w:v.appendChild(c.createTextNode(w)),n.appendChild(v),g.push(v)}j.insertBefore(n,o.nextSibling)}},s=function(a,b){var c=t();if(!!c){c.open("GET",a,!0),c.onreadystatechange=function(){c.readyState==4&&(c.status==200||c.status==304)&&b(c.responseText)};if(c.readyState==4)return;c.send()}},t=function(){var a=!1,b=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new XMLHttpRequest}],c=b.length;while(c--){try{a=b[c]()}catch(d){continue}break}return function(){return a}}();m(),respond.update=m,a.addEventListener?a.addEventListener("resize",u,!1):a.attachEvent&&a.attachEvent("onresize",u)}}(this,Modernizr.mq("only all")),function(a,b,c){function k(a){return!a||a=="loaded"||a=="complete"}function j(){var a=1,b=-1;while(p.length- ++b)if(p[b].s&&!(a=p[b].r))break;a&&g()}function i(a){var c=b.createElement("script"),d;c.src=a.s,c.onreadystatechange=c.onload=function(){!d&&k(c.readyState)&&(d=1,j(),c.onload=c.onreadystatechange=null)},m(function(){d||(d=1,j())},H.errorTimeout),a.e?c.onload():n.parentNode.insertBefore(c,n)}function h(a){var c=b.createElement("link"),d;c.href=a.s,c.rel="stylesheet",c.type="text/css";if(!a.e&&(w||r)){var e=function(a){m(function(){if(!d)try{a.sheet.cssRules.length?(d=1,j()):e(a)}catch(b){b.code==1e3||b.message=="security"||b.message=="denied"?(d=1,m(function(){j()},0)):e(a)}},0)};e(c)}else c.onload=function(){d||(d=1,m(function(){j()},0))},a.e&&c.onload();m(function(){d||(d=1,j())},H.errorTimeout),!a.e&&n.parentNode.insertBefore(c,n)}function g(){var a=p.shift();q=1,a?a.t?m(function(){a.t=="c"?h(a):i(a)},0):(a(),j()):q=0}function f(a,c,d,e,f,h){function i(){!o&&k(l.readyState)&&(r.r=o=1,!q&&j(),l.onload=l.onreadystatechange=null,m(function(){u.removeChild(l)},0))}var l=b.createElement(a),o=0,r={t:d,s:c,e:h};l.src=l.data=c,!s&&(l.style.display="none"),l.width=l.height="0",a!="object"&&(l.type=d),l.onload=l.onreadystatechange=i,a=="img"?l.onerror=i:a=="script"&&(l.onerror=function(){r.e=r.r=1,g()}),p.splice(e,0,r),u.insertBefore(l,s?null:n),m(function(){o||(u.removeChild(l),r.r=r.e=o=1,j())},H.errorTimeout)}function e(a,b,c){var d=b=="c"?z:y;q=0,b=b||"j",C(a)?f(d,a,b,this.i++,l,c):(p.splice(this.i++,0,a),p.length==1&&g());return this}function d(){var a=H;a.loader={load:e,i:0};return a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=r&&!s,u=s?l:n.parentNode,v=a.opera&&o.call(a.opera)=="[object Opera]",w="webkitAppearance"in l.style,x=w&&"async"in b.createElement("script"),y=r?"object":v||x?"img":"script",z=w?"img":y,A=Array.isArray||function(a){return o.call(a)=="[object Array]"},B=function(a){return Object(a)===a},C=function(a){return typeof a=="string"},D=function(a){return o.call(a)=="[object Function]"},E=[],F={},G,H;H=function(a){function f(a){var b=a.split("!"),c=E.length,d=b.pop(),e=b.length,f={url:d,origUrl:d,prefixes:b},g,h;for(h=0;h> Global +----------------------------------------------------------------------------------------------------*/ + +.grid_1, +.grid_2, +.grid_3 { + display:inline; + float: left; + position: relative; + margin-left: 1%; + margin-right: 1%; +} + +/* Grid >> Children (Alpha ~ First, Omega ~ Last) +----------------------------------------------------------------------------------------------------*/ + +.alpha { + margin-left: 0; +} + +.omega { + margin-right: 0; +} + +/* Grid >> 3 Columns +----------------------------------------------------------------------------------------------------*/ + + +.container_3 .grid_1 { + width:31.333%; +} + +.container_3 .grid_2 { + width:64.667%; +} + +.container_3 .grid_3 { + width:98.0%; +} + + + +/* Prefix Extra Space >> 3 Columns +----------------------------------------------------------------------------------------------------*/ + + +.container_3 .prefix_1 { + padding-left:33.333%; +} + +.container_3 .prefix_2 { + padding-left:66.667%; +} + + + +/* Suffix Extra Space >> 3 Columns +----------------------------------------------------------------------------------------------------*/ + + +.container_3 .suffix_1 { + padding-right:33.333%; +} + +.container_3 .suffix_2 { + padding-right:66.667%; +} + + + +/* Push Space >> 3 Columns +----------------------------------------------------------------------------------------------------*/ + + +.container_3 .push_1 { + left:33.333%; +} + +.container_3 .push_2 { + left:66.667%; +} + + + +/* Pull Space >> 3 Columns +----------------------------------------------------------------------------------------------------*/ + + +.container_3 .pull_1 { + left:-33.333%; +} + +.container_3 .pull_2 { + left:-66.667%; +} + + + + +/* Clear Floated Elements +----------------------------------------------------------------------------------------------------*/ + +/* http://sonspring.com/journal/clearing-floats */ + +.clear { + clear: both; + display: block; + overflow: hidden; + visibility: hidden; + width: 0; + height: 0; +} + +/* http://perishablepress.com/press/2008/02/05/lessons-learned-concerning-the-clearfix-css-hack */ + +.clearfix:after { + clear: both; + content: ' '; + display: block; + font-size: 0; + line-height: 0; + visibility: hidden; + width: 0; + height: 0; +} + +.clearfix { + display: inline-block; +} + +* html .clearfix { + height: 1%; +} + +.clearfix { + display: block; +}/* eo 960gs*/ + + +*{text-shadow: 0 1px 0 white} +body{font-size: 12px} +a{text-decoration: none; font-weight: bold; color: #333} +a:hover{color: #000} +/* Typography */ +h1,h2,h3,h4,h5{font-weight: normal; color: #666} +/* eo Typography */ + +/* Forms */ +input[type="text"]:focus, input[type="password"]:focus { outline: none; } +input.text{border: 1px solid #ccc; border-radius: 4px; display: block; padding: 10px} +/* eo Forms */ + +/* Buttons */ +.grey-button{ + border-radius: 5px; + font-size: 12px; + font-weight: bold; + padding: 6px 20px; + border: 1px solid #999; + color: #666; + box-shadow: 0 1px 2px rgba(0,0,0,.3); + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #f7f7f7), to(#d5d5d5)); + background-image: -webkit-linear-gradient(#f7f7f7 7.6%, #d5d5d5); + background-image: -moz-linear-gradient(#f7f7f7 7.6%, #d5d5d5); + background-image: -o-linear-gradient(#f7f7f7 7.6%, #d5d5d5); +} + +.button{ + padding: 10px 20px; + text-align: center; + display: inline-block; + border-radius: 5px; + color: #578E91; + font-size: 12px; + text-transform: uppercase; + border: 1px solid #8CE2E6; + background-image: -webkit-gradient(linear, 0 0, 0 34, color-stop(0.794, #dbf5f6), to(#c5eef0)); + background-image: -webkit-linear-gradient(#dbf5f6 79.4%, #c5eef0); + background-image: -moz-linear-gradient(#dbf5f6 79.4%, #c5eef0); + background-image: -o-linear-gradient(#dbf5f6 79.4%, #c5eef0); +} + +.button:hover{color: rgba(0,0,0,.8)} + +.button.green{ + margin-right: 0; +} + +.button.yellow{ + color: #908054; + border-color: #DDCDA1; + background-image: -webkit-gradient(linear, 0 0, 0 34, color-stop(0.794, #FFEFC3), to(#F3E3B7)); + background-image: -webkit-linear-gradient(#FFEFC3 79.4%, #F3E3B7); + background-image: -moz-linear-gradient(#FFEFC3 79.4%, #F3E3B7); + background-image: -o-linear-gradient(#FFEFC3 79.4%, #F3E3B7); +} + +/* eo Buttons */ + +/* UI Box */ +.ui-box{border: 1px solid #DEDFE1; float: left; border-radius: 5px} +.ui-box h3{ + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); + background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); + background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); + background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); + margin: 0; + padding: 1em; + font-size: 12px; + font-weight: normal; + font-size: 16px; + border-bottom: 1px solid #DEDFE1; + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + +.ui-box h3 a{font-weight: normal;} + +.ui-box .data{padding: .5em 1em} + +.ui-box .buttons{background-color: #f7f8f9; padding: 1em; + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; +} + +.ui-box:hover{box-shadow: 0 0 10px rgba(0,0,0,.1); border: 1px solid #ccc; + + -webkit-transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715); + -moz-transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715); + -o-transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715); + transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715); +} + +/* eo UI Box */ + +/* Login Page */ +body.login-page{background-color: #f1f1f1; padding-top: 10%} + +.login-box{ + width: 304px; + position: relative; + border-radius: 5px; + margin: auto; + padding: 20px; + background: white; + box-shadow: rgba(0, 0, 0, 0.07) 0 1px 0,white 0 2px 0,rgba(0, 0, 0, 0.07) 0 3px 0,white 0 4px 0, rgba(0, 0, 0, 0.07) 0 5px 0; +} + +.login-box .login-logo{ + margin: 10px 0 30px 0; + display: block; +} + +.login-box input.text{background-color: #f1f1f1; font-size: 16px; border-radius: 0; padding: 14px 10px; width: 280px} + +.login-box input.text.top{ + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + +.login-box input.text.bottom{ + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; + border-top: 0; + margin-bottom: 20px; +} + +.login-box a.forgot{float: right; padding-top: 6px} + + +/* General */ +header{background: #474D57 url('bg-header.png') repeat-x bottom; overflow: hidden; padding: 10px 2% 6px 2%} +header a{color: white; text-shadow: 0 -1px 0 black} +header a:hover{color: #f1f1f1} +header h1{ + width: 65px; +} +header h1.logo{ + background: url('images.png') no-repeat -3px -6px; + width: 65px; + height: 26px; + margin: 5px 0; + padding: 0; + float: left; + text-indent: -1000em; +} +header nav{border-radius: 4px; box-shadow: 0 1px 2px black; width: 321px; margin: auto; + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595d63), to(#31363e)); + background-image: -webkit-linear-gradient(#595d63 6.6%, #31363e); + background-image: -moz-linear-gradient(#595d63 6.6%, #31363e); + background-image: -o-linear-gradient(#595d63 6.6%, #31363e); + margin-top: 2px; +} +header nav a{padding: 8px 12px 8px 34px; display: inline-block; color: #D6DADF; border-right: 1px solid #31363E; position: relative; box-shadow: 1px 0 0 rgba(255,255,255,.1); margin: 0} +header nav a span{width: 20px; height: 20px; display: inline-block; background: red; position: absolute; left: 8px; top: 6px;} +header nav a:last-child {border: 0; box-shadow: none} +header nav a:hover, header nav a.current{ + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595d63), to(#2c2f35)); + background-image: -webkit-linear-gradient(#595d63 6.6%, #2c2f35); + background-image: -moz-linear-gradient(#595d63 6.6%, #202227); + background-image: -o-linear-gradient(#595d63 6.6%, #202227); +} + +header nav a:active{ + box-shadow: 0 1px 4px rgba(0,0,0,.8) inset; +} + + +header nav a.dashboard { + -webkit-border-top-left-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-topleft: 4px; + -moz-border-radius-bottomleft: 4px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} + +header nav a.admin{ + -webkit-border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-topright: 4px; + -moz-border-radius-bottomright: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +header nav a.dashboard span{background: url('images.png') no-repeat -161px -4px; width: 20px; height: 20px; } +header nav a.admin span{background: url('images.png') no-repeat -184px -4px; width: 20px; height: 20px;} +header nav a.project span{background: url('images.png') no-repeat -209px -5px; width: 20px; height: 18px; top: 7px} + +header .login-top{float: right; width: 180px; + background-image: -webkit-gradient(linear, 0 0, 0 62, color-stop(0.032, #464c56), to(#363c45)); + background-image: -webkit-linear-gradient(#464c56 3.2%, #363c45); + background-image: -moz-linear-gradient(#464c56 3.2%, #363c45); + background-image: -o-linear-gradient(#464c56 3.2%, #363c45); + padding: 0 10px; + height: 44px; +} +header .login-top a{display: block;} +header .login-top a.pic{float: left; margin-right: 10px; + img{ height: 36px; width: 36px; border: 1px solid black} +} +header .login-top a.username{margin-bottom: 5px} +header .login-top a.logout{color: #ccc} +header{margin-bottom: 0; clear: both; } + +.page-title{background-color: #f1f1f1;display: block; float: left; clear: both; width: 98%; padding: 0 1%; border-bottom: 1px solid #ccc; box-shadow: 0 -1px 0 white inset; margin-bottom: 1.5em} +.page-title a.grey-button{float: right;} + + + + +/* Project Page */ +.project-page .page-title{margin-bottom: 0} +.project-page .project-sidebar {width: 220px; margin-right: 1%; background: #f7f7f7; overflow: hidden; padding: 20px 0 20px 2%; margin: 0} +.project-page .project-sidebar input.text.git-url{width: 90%; box-shadow: 0 1px 2px rgba(0,0,0,.2) inset; padding: 3% 2%; margin: 0% 10% 7% 0} +.project-page .project-sidebar aside a{display: block; background: white; padding: 15px 10px; border-bottom: 1px solid #eee} +.project-page .project-sidebar aside a:first-child{ + -webkit-border-top-left-radius: 5px; + -moz-border-radius-topleft: 5px; + border-top-left-radius: 5px; +} +.project-page .project-sidebar aside a:last-child{ + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomleft: 5px; + border-bottom-left-radius: 5px; +} +.project-page .project-sidebar aside a.current{background-color: #4bb8d2; color: white; text-shadow: none; border-color: transparent} +.project-page .project-content{ float: left; padding: 20px} +.project-page .project-content h2{margin-top: 0} +/* eo Project Page */ + +/* Projects Page */ +.project-box.ui-box .data .repository {margin-bottom: 20px} +.project-box.ui-box .data .title span{width: 80px; text-align: right; padding-right: 10px; display: inline-block; font-weight: bold;} +.project-box{width: 100%; margin-bottom: 3em} +.browse-code{margin-right: 10px} +/* eo Projects Page */ + + +/* ==|== non-semantic helper classes ======================================== */ +.ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; } +.ir br { display: none; } +.hidden { display: none !important; visibility: hidden; } +.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } +.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } +.invisible { visibility: hidden; } +.clearfix:before, .clearfix:after { content: ""; display: table; } +.clearfix:after { clear: both; } +.clearfix { zoom: 1; } + + +/* ==|== media queries ====================================================== */ + +@media only screen and (min-width: 480px) { + + +} + +@media only screen and (min-width: 768px) { + +} + + + +/* ==|== print styles ======================================================= */ + +@media print { + * { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } + a, a:visited { text-decoration: underline; } + a[href]:after { content: " (" attr(href) ")"; } + abbr[title]:after { content: " (" attr(title) ")"; } + .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } + pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } + thead { display: table-header-group; } + tr, img { page-break-inside: avoid; } + img { max-width: 100% !important; } + @page { margin: 0.5cm; } + p, h2, h3 { orphans: 3; widows: 3; } + h2, h3 { page-break-after: avoid; } +} diff --git a/app/views/layouts/_head_panel.html.erb b/app/views/layouts/_head_panel.html.erb index 07de8de4..e6f36e3f 100644 --- a/app/views/layouts/_head_panel.html.erb +++ b/app/views/layouts/_head_panel.html.erb @@ -1,22 +1,41 @@ -
      + +
      +

      + GITLAB

      + + + +
      + + +
      <%= link_to truncate(@project.name, :length => 20), project_path(@project), :class => "current button" if @project && !@project.new_record? %> + <%= link_to 'Dashboard', dashboard_path, :class => current_page?(dashboard_path) ? "current button" : "button" %> <%= link_to 'Projects', projects_path, :class => current_page?(projects_path) ? "current button" : "button" %> <%= link_to('Admin', admin_root_path, :class => admin_namespace? ? "current button" : "button" ) if current_user.is_admin? %> <%= link_to profile_path, :class => ((controller.controller_name == "keys" || controller.controller_name == "profile") ? "current button" : "button") do %> diff --git a/config/routes.rb b/config/routes.rb index 5f95e113..bac472a2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -15,6 +15,7 @@ Gitlab::Application.routes.draw do put "profile/password", :to => "profile#password_update" put "profile/edit", :to => "profile#social_update" get "profile", :to => "profile#show" + get "dashboard", :to => "dashboard#index" #get "profile/:id", :to => "profile#show" resources :projects, :only => [:new, :create, :index] diff --git a/lib/commit_ext.rb b/lib/commit_ext.rb index 411809f0..32706acb 100644 --- a/lib/commit_ext.rb +++ b/lib/commit_ext.rb @@ -8,4 +8,8 @@ module CommitExt rescue "-- invalid encoding for commit message" end + + def created_at + committed_date + end end From d405292388c642117c8300a0a4931fc9a4eb1f66 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 1 Nov 2011 11:00:59 +0200 Subject: [PATCH 145/176] project page fixed --- app/assets/images/images.png | Bin 6472 -> 8698 bytes app/assets/stylesheets/style.scss | 294 +++++++++++++++++++----- app/views/layouts/_page_title.html.haml | 2 +- app/views/layouts/application.html.haml | 2 +- app/views/projects/_tile.html.haml | 2 +- app/views/projects/index.html.haml | 9 +- 6 files changed, 244 insertions(+), 65 deletions(-) diff --git a/app/assets/images/images.png b/app/assets/images/images.png index 8af7472e70e1030ccb44952f287964cf460cbe20..973d3bdd39d36e963223a1281ab44a5af453fe82 100644 GIT binary patch literal 8698 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 literal 6472 zcmeI1`CpRh*T-pWvYASw95dIxI8A;h&2e(gg-Xn6G99MU%mq`)G!=JL6k2AAH05y` zwbZn1a>jJ^GzHv{9iFQ{;Q96Wsq6K+fcv^{Ue~$L`JDGTH{AWj z+jG~~hF?Pr@U}JaIG~IZC}xbV@;D|GEMuEd zXuW+d)uyq@CUDt+xO3oHal!Uyzb0TN4h(Q-|L{F+R2^gKfy}R|`OWt$hcu5OhpNb0 zFO+TUCA)ox$h#jC=l*j$H0~_KsQruVm{ud}mm}E%PLN2rnEkN*RXUboultgq%J^&G z-SWEpRYM%YwH+ zCU5Ocg8bBG`%&9=34|+6qJv*qwMFp{HxR5&<@_;sd zG}=~AeCC?!{U~E-boaw5Ye@r|dlk~#dGCaEcbzk=xmdjsg4AoNNSpXbY;3{PD=o50 z>nugN#G%AgjdoV~LUHW=#MGD>RWWbrM!AK&_wU@EbXYm2c_d@hc+Txm4kX28qu;$u zBowMSQmOR9P!uhd{|F0%l`|MBAGh^~eM&U#(m0pRUdOPcoz`ypG>F3&PTab~P#c11 zf`Jus>iLr<*bl4ouXN$cyU9z#Gz4OqQy*~}5h&|-*CjU#o0kfLl7}v6Tw$le3ZM#G z(Lh4C6}@3RjsGaS@JLYeU-k9tS>TJAwKX+0&ak&y+Bz=7Ty9HdYHDg+T-?f|8174x z#l^+QXcr5oxZa9g>HY<}hz`_Q*}CrAIwi>i8C|+28G^3fs!+Hhv-$9nR|*LN!Q0vW zpr-6pN4Z?UB&LQG@x6lZuXJIsE7HIW}`&bLka?6Lr^O(6x+wh%bZh|rAx&arVQ@cL9O~7do1UH^#|Iu5mqz?qZ!C?m~h;D zYNlF%mpI0U;%S$1h{T!KB>Ff`#6UI6=8FkGI5}}P|Jh+}8NkA;RA;+Ots2P=6R9&w z5nj@A&6g6)pw`qZnFS@hIaoa3Q%ryU>=_#GU*Li0c$IO{)p^au)#U+8~AB@*-U@^a-W15?x5q~v6k zV3-`hYh9{sG0i3JwOQX#C?m=;H*3xmST@lq6w1}e$VkmFohg1g5{x4o?B9QvNVK~) zY}q=K>nzNi$#KYf^XAP(W`;}`yF3~{JztDbd%SCeowYR`XP zX4Rdb{`cRXkYwLV?>GC<{wau#N@r(hO?Xd{9hQ8F_ED3RlA=~nGUg8Vor-a|S)~;b z(+o`y`zzfR)|_2FdZA!$p4doHOK_ob+am0fXGA{L8jxj8wVTDmSPV^;JJbsvGRF^c5~ zI4%;Y2aKEP+=nv8%|DEoXjTYYMtp0AhCxWi_d)3h!S$DmHz)Q$*I#0IZW)Wu3Uh-J zd+gTDVZj-zooqMEI?pt7V}Kg=I(L_63<1}@vpe>M;-Hazw6x_=S;m^Q)D<^jnHAdp z$H6oDLGhj6?9jKmG}s){ezSl`+-1StJRkAwcwT4e*Y}dwl!j9Lsg-fN_libp?6pf8 zSRqps4L_+|OeAY|k7U=g_W)_UjBaAk>DbN=1i6@}oOhteK$w0ACj0Ufk}8WVi!2y( zH3t)Tj_ezjk>Qe#!}&#X>gF~n1l5vmmqPbSwxiuRGh}_fhk_aXdx|N_6yY?n1LYn- z%un3!ycKZiy7zK(bH`I>at_xr@HI+M@R%?v>FGPJ|YIL@=`Q$VW9)y zlwb6RMw{WeuT|*ZP5l$fV`kn*Dlnqd?Z@JDDsuaawVZ6{sM<5rawyN=?#Mb!MP;n9=6@=p+FNuA2hcEfk zPzp#K#|&v4hr{s)Chfa6QmaZpxa^@Fu-9hnf$q3{=Z=Q?Yjt4a%4E9?u*Bl|P?Y(Y zCXCNKd ziJQSw0TXg-D9mPaSSVnm^2r_3^d}Zs(zQZXEB?(N2lLA-*`W|(;KZ-7IeeI8H>uxE6= z56+Sd2VjC2QA5u`tibNc(b3UK;o;%!AX}HYbj);hWoddM@cUu7xZ0X)c%jy z9Em437-2c~GKMQI3`{uvdUiJa9*Oi?Dot&bPG@^!g&$-rSSSJEB^+{Rd9>_n*WOBay9i2y; zC33v7YtXID-?@0;xDQ*v)WzEMPW-7go#GLrQOX@9S~IXC%w0v6fcp~w}gC+nptHU-&HG((k2l_M&kd;6yxgz0aJ z#orwEeUZx35=TmI5J&gXGDq%%B(^XT4K&u0S|f~H_d${G^frh@l|oVog%+alvIf$~ zE#bSIHmBmm{w2jDoLilp6Ru}!;+x8fUieS_@IMBe5))_t&0}_E@6+6pCrJnI)S&%! z96Z;b6$YpCu0;fF8ev*juMh~Dte>C#hyhGA0g}l^cNYZ77oL*vb30Jde=?y1Yxm2P zv(29jbOwt2Ve#u zkLK*9MM|2C4IIej7H)N_#oUClAq1kt1+SFecXxM3J%AI`kxNLuPHI6xfjRrj_@tzU z49PgQjJVim=wJ$c{W6-fCLlIm8E;N@;DHK{LN&%+2H4E@$ktcYfU>BOfj(mt^h9q_ z8u$}8P{eQt{7{QRE}>X;nUyMLcH zvv?^WARDwFsySe z_ft=jP_VSL#G1NoRQ_wVttPXM#nPyWj^|NbN#+}Sq47x|>W|^OYfV&Qw!MFi|kR?cvIbb#Rh?15{|{K&s=)^*6e(oyGY`l6-`@N#g}#$CJxi1uwbkPEZ`X%+hA_SS)bJ zY)F`Un@c2SDmHUmWV82KO{z^U3p7cE=Sx$k@3IuDB!V(z(0;pj*E{ot`_T9obh-qC z*C=?DNDKzW0y*vzls1>|cLc@EXh#QiqFUr%0g zlmwKe;DeIW`hrZh`qYrs0%Ct^g+R|XO2_c>TydMx9Pr^OQZdFEc;IyVzIaZTrCjS~ z8Jd`o3(#rP;67%|xMO4L(_w>w)#tz4wryK!ntZX62ik!X7>o!5n;v&mh1;>oio8SM z-X9Vdf*lBt2rX`m%LR`Cj;Wvk+|mMr z(z^CGWUxY9skmg^w*QgMf(J6mvlW{wS;SAyW?a?T3}Y)l%tmW>iEZz+Savh3Vzz!T zp|Qsj@Lq_R-&_r#oobarBLOd{i@*RY&x#15{22!*?ccMftl~U@6Log(+^G}-gkJiE(0jK^z;@GviV#-K^(u=q9o0nB?6K|A zxIyoe^$T>CO2En`cAZGQh2$Q0G_0)P@YmL>MLiINRj)hJ*<@KMPd@0K`MQ;QButDZ z4T<`siUmkwJarpG_V330RqNbym6fjiqh0Y6wxJ`AWio1&$IGKp@%O4cRuC#`-UD?_ zRJ|3>B`PA!c_3+#0_R^W$&#g(6kRDh6K-Tv`hu16m)b4oOk)3`;vw-CmrN4q1GJo$LNTf3Kk!MNEP>2+M}cOMI>Riwe0!TpopO`m_zw@F+%<#=fN z{4c!XEQoP2|n01zBq_HG1Dj)5nM~js1ivPH<`WimXX4;n((JuQT^@=N<-9Om&>TL++*pKEg zHOxCRh|G`n(}Nt*W1HyFouc9c^q{=bsa4YZXx>+FwtAg-R6DZ*72d-4I=l_C?|Jn( zArij-47TK0p|YW3A&~-2A-o*&m yield(:body_class), :id => yield(:boyd_id)} #container = render :partial => "layouts/flash" = render :partial => "layouts/head_panel" diff --git a/app/views/projects/_tile.html.haml b/app/views/projects/_tile.html.haml index ced0bf3b..7c0b8679 100644 --- a/app/views/projects/_tile.html.haml +++ b/app/views/projects/_tile.html.haml @@ -1,7 +1,7 @@ - @projects.in_groups_of(3, false) do |projects| - projects.each_with_index do |project, i| %div.grid_1 - %div{ :class => "project-box ui-box ui-box-big", :style => i == 2 ? "" : "margin-right:30px;" } + %div{ :class => "project-box ui-box ui-box-big" } = link_to project_path(project) do %h3= project.name .data diff --git a/app/views/projects/index.html.haml b/app/views/projects/index.html.haml index 45187b44..a35ead82 100644 --- a/app/views/projects/index.html.haml +++ b/app/views/projects/index.html.haml @@ -1,8 +1,9 @@ +- content_for(:body_class, "projects-page") - content_for(:page_title) do - .grid-4 - %h2.icon - - if current_user.can_create_project? - %a.grey-button.right{:href => new_project_path} Create new project + .grid_4 + - if current_user.can_create_project? + %a.grey-button.right{:href => new_project_path} Create new project + %h2.icon %span Projects From 0903932320073e3e5120faae523e00a94709a95a Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 1 Nov 2011 11:22:16 +0200 Subject: [PATCH 146/176] updated --- app/controllers/commits_controller.rb | 1 + app/controllers/snippets_controller.rb | 1 + app/controllers/team_members_controller.rb | 1 + app/views/layouts/project.html.haml | 50 +++++++++++----------- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index 83071891..79b97ed7 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -2,6 +2,7 @@ require "base64" class CommitsController < ApplicationController before_filter :project + layout "project" # Authorize before_filter :add_project_abilities diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index d9a6ab2a..54ad6019 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -1,6 +1,7 @@ class SnippetsController < ApplicationController before_filter :authenticate_user! before_filter :project + layout "project" # Authorize before_filter :add_project_abilities diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb index 48e7e9b9..8a4e32e5 100644 --- a/app/controllers/team_members_controller.rb +++ b/app/controllers/team_members_controller.rb @@ -1,5 +1,6 @@ class TeamMembersController < ApplicationController before_filter :project + layout "project" # Authorize before_filter :add_project_abilities diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index 68f973dc..acf57bd1 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -14,32 +14,32 @@ #container = render :partial => "layouts/flash" = render :partial => "layouts/head_panel" - = render :partial => "layouts/page_title" .project-container - .project-sidebar.grid_1 - %input.git-url.text{:id => "", :name => "", :readonly => "", :type => "text", :value => @project.url_to_repo} - %aside - = link_to image_tag("home.png", :width => 20), project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil - = link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil - = link_to "Commits", project_commits_path(@project), :class => current_page?(:controller => "commits", :action => "index", :project_id => @project) ? "current" : nil - = link_to team_project_path(@project), :class => (current_page?(:controller => "projects", :action => "team", :id => @project) || controller.controller_name == "team_members") ? "current" : nil do - Team - - if @project.users_projects.count > 0 - %span{ :class => "top_menu_count" }= @project.users_projects.count - = link_to project_issues_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do - Issues - - if @project.issues.opened.count > 0 - %span{ :class => "top_menu_count" }= @project.issues.opened.count - = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do - Wall - - if @project.common_notes.count > 0 - %span{ :class => "top_menu_count" }= @project.common_notes.count - = link_to project_snippets_path(@project), :class => (controller.controller_name == "snippets") ? "current" : nil do - Snippets - - if @project.snippets.count > 0 - %span{ :class => "top_menu_count" }= @project.snippets.non_expired.count - - if @commit - = link_to truncate(commit_name(@project,@commit), :length => 15), project_commit_path(@project, :id => @commit.id), :class => current_page?(:controller => "commits", :action => "show", :project_id => @project, :id => @commit.id) ? "current" : nil + .project-sidebar + .fixed + %input.git-url.text{:id => "", :name => "", :readonly => "", :type => "text", :value => @project.url_to_repo} + %aside + = link_to image_tag("home.png", :width => 20), project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil + = link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil + = link_to "Commits", project_commits_path(@project), :class => current_page?(:controller => "commits", :action => "index", :project_id => @project) ? "current" : nil + = link_to team_project_path(@project), :class => (current_page?(:controller => "projects", :action => "team", :id => @project) || controller.controller_name == "team_members") ? "current" : nil do + Team + - if @project.users_projects.count > 0 + %span{ :class => "top_menu_count" }= @project.users_projects.count + = link_to project_issues_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do + Issues + - if @project.issues.opened.count > 0 + %span{ :class => "top_menu_count" }= @project.issues.opened.count + = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do + Wall + - if @project.common_notes.count > 0 + %span{ :class => "top_menu_count" }= @project.common_notes.count + = link_to project_snippets_path(@project), :class => (controller.controller_name == "snippets") ? "current" : nil do + Snippets + - if @project.snippets.count > 0 + %span{ :class => "top_menu_count" }= @project.snippets.non_expired.count + - if @commit + = link_to truncate(commit_name(@project,@commit), :length => 15), project_commit_path(@project, :id => @commit.id), :class => current_page?(:controller => "commits", :action => "show", :project_id => @project, :id => @commit.id) ? "current" : nil .project-content From 84397ce88c09d30e14fef5d8e6a6e559ae0dcb7c Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 1 Nov 2011 12:48:26 +0200 Subject: [PATCH 147/176] commits page --- app/assets/stylesheets/projects.css.scss | 48 ------------------------ app/views/commits/_commits.html.haml | 41 ++++++++++---------- app/views/commits/index.html.haml | 1 + app/views/layouts/project.html.haml | 12 +++--- 4 files changed, 29 insertions(+), 73 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index e5184a7e..418a6e82 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -102,54 +102,6 @@ table.round-borders { float:left; } -.day-commits-table { - @include round-borders-all(4px); - padding: 4px 0px; - margin-bottom:10px; - display:block; - width:100%; - background: #E6F1F6; - - .day-header { - padding:10px; - h3 { - margin:0px; - } - } - - ul { - display:block; - list-style:none; - margin:0px; - padding:0px; - - li.commit { - display:list-item; - padding:8px; - margin:0px; - background: #F7FBFC; - border-top: 1px solid #E2EAEE; - - &:first-child { - border-top: 1px solid #E2EAEE; - } - &:nth-child(2n+1) { - background: white; - } - - a.button { - width:85px; - padding:10px; - margin:0px; - float:right; - } - p { - margin-bottom: 3px; - font-size: 13px; - } - } - } -} @mixin panel-color { background: #111 !important; background: -webkit-gradient(linear,left top,left bottom,from(#333),to(#111)) !important; diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index 99823065..36225d37 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -1,22 +1,25 @@ - @commits.group_by { |c| c.committed_date.to_date }.each do |day, commits| - .day-commits-table - .day-header + %div{ :class => "commits-date ui-box ui-box-small ui-box-big" } + .day-commits-table %h3= day.stamp("28 Aug, 2010") - %ul - - commits.each do |commit| - %li{ :class => "commit", :url => project_commit_path(@project, :id => commit.id) } - - if commit.author.email - = image_tag gravatar_icon(commit.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" - - else - = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" - %p - %strong - = truncate(commit.safe_message, :length => 60) - = link_to "Browse Code", tree_project_path(@project, :commit_id => commit.id), :class => "lite_button", :style => "float:right" - = link_to truncate(commit.id.to_s, :length => 16), project_commit_path(@project, :id => commit.id), :class => "lite_button", :style => "width:120px;float:right" - %span - %span.author - = commit.author - = time_ago_in_words(commit.committed_date) - ago + .data + - commits.each do |commit| + %a{ :class => "commit", :href => project_commit_path(@project, :id => commit.id) } + %span.commit-info + %data.commit-button + = truncate(commit.id.to_s, :length => 16) + %i + %data.commit-browse{ :onclick => "location.href='#{tree_project_path(@project, :commit_id => commit.id)}';return false;"} + Browse Code + - if commit.author.email + = image_tag gravatar_icon(commit.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" + - else + = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" + %span.commit-title + %strong + = truncate(commit.safe_message, :length => 60) + %span.commit-author + %strong= commit.author + = time_ago_in_words(commit.committed_date) + ago = more_commits_link if @commits.size > 99 diff --git a/app/views/commits/index.html.haml b/app/views/commits/index.html.haml index 452e13f8..92a382a9 100644 --- a/app/views/commits/index.html.haml +++ b/app/views/commits/index.html.haml @@ -1,3 +1,4 @@ +- content_for(:body_class, "project-page commits-page") %div %h3 .left diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index acf57bd1..619952f1 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -10,7 +10,7 @@ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body.project-page + %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)} #container = render :partial => "layouts/flash" = render :partial => "layouts/head_panel" @@ -19,25 +19,25 @@ .fixed %input.git-url.text{:id => "", :name => "", :readonly => "", :type => "text", :value => @project.url_to_repo} %aside - = link_to image_tag("home.png", :width => 20), project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil + = link_to "History", project_path(@project), :class => current_page?(:controller => "projects", :action => "show", :id => @project) ? "current" : nil = link_to "Tree", tree_project_path(@project), :class => current_page?(:controller => "projects", :action => "tree", :id => @project) ? "current" : nil = link_to "Commits", project_commits_path(@project), :class => current_page?(:controller => "commits", :action => "index", :project_id => @project) ? "current" : nil = link_to team_project_path(@project), :class => (current_page?(:controller => "projects", :action => "team", :id => @project) || controller.controller_name == "team_members") ? "current" : nil do Team - if @project.users_projects.count > 0 - %span{ :class => "top_menu_count" }= @project.users_projects.count + %span{ :class => "number" }= @project.users_projects.count = link_to project_issues_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do Issues - if @project.issues.opened.count > 0 - %span{ :class => "top_menu_count" }= @project.issues.opened.count + %span{ :class => "number" }= @project.issues.opened.count = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do Wall - if @project.common_notes.count > 0 - %span{ :class => "top_menu_count" }= @project.common_notes.count + %span{ :class => "number" }= @project.common_notes.count = link_to project_snippets_path(@project), :class => (controller.controller_name == "snippets") ? "current" : nil do Snippets - if @project.snippets.count > 0 - %span{ :class => "top_menu_count" }= @project.snippets.non_expired.count + %span{ :class => "number" }= @project.snippets.non_expired.count - if @commit = link_to truncate(commit_name(@project,@commit), :length => 15), project_commit_path(@project, :id => @commit.id), :class => current_page?(:controller => "commits", :action => "show", :project_id => @project, :id => @commit.id) ? "current" : nil From e8d10b321716154421a0642e4d9f48d00c3aa56b Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 1 Nov 2011 13:17:36 +0200 Subject: [PATCH 148/176] issues fix layout --- app/assets/stylesheets/projects.css.scss | 13 +++++++++++++ app/views/issues/show.html.haml | 4 ++-- app/views/projects/show.html.haml | 4 ++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 418a6e82..e60dc701 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -660,3 +660,16 @@ tbody tr:nth-child(2n) td, tbody tr.even td { .right { float:right; } + +.width-50p{ + width:50%; +} +.width-49p{ + width:49%; +} +.width-30p{ + width:30%; +} +.width-65p{ + width:65%; +} diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index c6105283..371a8033 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -1,9 +1,9 @@ %h2 = "Issue ##{@issue.id} - #{html_escape(@issue.title)}" -.span-15 +.left.width-65p -#= simple_format html_escape(@issue.content) .issue_notes= render "notes/notes" -.span-8.right +.right.width-30p .span-8 - if @issue.closed %center.success Closed diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 56621785..ff352437 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -13,11 +13,11 @@ = label_tag "week_view","Week" .clear %hr -.span-11 +.left.width-49p %h3 Commits =render "projects/recent_commits" -.span-11.right +.right.width-49p %h3 Talk =render "projects/recent_messages" From 82d16ccfd189f5bdc65090ac7af1d4eef1f1774e Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 1 Nov 2011 22:11:24 +0200 Subject: [PATCH 149/176] commits + tree in progress --- app/assets/stylesheets/projects.css.scss | 41 ++++++++++++++--- app/views/commits/index.html.haml | 45 +++++++++++++------ app/views/issues/_issues.html.haml | 2 +- app/views/layouts/_page_title.html.haml | 5 --- app/views/layouts/project.html.haml | 1 - app/views/projects/_team.html.haml | 2 +- app/views/projects/_tree.html.haml | 56 +++++++++++++++--------- 7 files changed, 104 insertions(+), 48 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 66db914a..d8e04318 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -335,11 +335,6 @@ input.ssh_project_url { border-width: 1px; } -tbody tr:nth-child(2n) td, tbody tr.even td { - background: none repeat scroll 0 0 #F7FBFC; - border-top: 1px solid #E2EAEE; - border-bottom: 1px solid #E2EAEE; -} .top_menu_count { background: none repeat scroll 0 0 white; @@ -672,6 +667,42 @@ tbody tr:nth-child(2n) td, tbody tr.even td { } .width-65p{ width:65%; +} pre.commit_message { white-space: pre-wrap; } + +#container { + min-height:100%; +} +.ui-selectmenu{ + @include round-borders-all(4px); + margin-right:10px; + font-size:1.5em; + height:auto; + font-weight:bold; + .ui-selectmenu-status { + padding:3px 10px; + } +} + +td.code { + width: 100%; + .highlight { + margin-left: 55px; + overflow:auto; + overflow-y:hidden; + } +} +.highlight pre { + white-space: pre; + word-wrap:normal; +} + +.highlighttable tr:hover { + background:white; +} +table.highlighttable pre{ + line-height:16px !important; + font-size:12px !important; +} diff --git a/app/views/commits/index.html.haml b/app/views/commits/index.html.haml index 92a382a9..f8928b6f 100644 --- a/app/views/commits/index.html.haml +++ b/app/views/commits/index.html.haml @@ -1,16 +1,33 @@ - content_for(:body_class, "project-page commits-page") -%div - %h3 - .left - = form_tag project_commits_path(@project), :method => :get do - = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches" -   - .left.prepend-1 - = form_tag project_commits_path(@project), :method => :get do - = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags" - = text_field_tag "ssh", @project.url_to_repo, :class => ["ssh_project_url", "one_click_select"] - .clear + +.left + = form_tag project_commits_path(@project), :method => :get do + = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches" +.left + = form_tag project_commits_path(@project), :method => :get do + = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags" +.clear + +%br + + +-#%a.right.button{:href => "#"} Download +-#-if can? current_user, :admin_project, @project + %a.right.button.blue{:href => "#"} EDIT +%h2.icon + %span + %a.project-name{:href => "#"} + %i.arrow> + Project +   + %d + %a{:href => "#"} + = @ref - if params[:path] - %h3{:style => "color:#555"} /#{params[:path]} - %div{:id => dom_id(@project)} - = render "commits" +   + %d + %a{:href => "#"}= params[:path].split("/").join(" / ") + + +%div{:id => dom_id(@project)} + = render "commits" diff --git a/app/views/issues/_issues.html.haml b/app/views/issues/_issues.html.haml index 11e4c38e..a6a38e69 100644 --- a/app/views/issues/_issues.html.haml +++ b/app/views/issues/_issues.html.haml @@ -1,5 +1,5 @@ %table.round-borders#issues-table - %tr + %thead - if can?(current_user, :admin_issue, @project) && !params[:f] || params[:f] == "0" %th %th Assignee diff --git a/app/views/layouts/_page_title.html.haml b/app/views/layouts/_page_title.html.haml index ec8fa89d..ea72b25a 100644 --- a/app/views/layouts/_page_title.html.haml +++ b/app/views/layouts/_page_title.html.haml @@ -1,7 +1,2 @@ - if content_for?(:page_title) = yield :page_title -- else - .grid_4 - .container_3 - %h2.icon - %span= controller.controller_name.capitalize diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index 619952f1..b4b51631 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -41,6 +41,5 @@ - if @commit = link_to truncate(commit_name(@project,@commit), :length => 15), project_commit_path(@project, :id => @commit.id), :class => current_page?(:controller => "commits", :action => "show", :project_id => @project, :id => @commit.id) ? "current" : nil - .project-content = yield diff --git a/app/views/projects/_team.html.haml b/app/views/projects/_team.html.haml index 4001c7a2..d12ccac7 100644 --- a/app/views/projects/_team.html.haml +++ b/app/views/projects/_team.html.haml @@ -2,7 +2,7 @@ %div#new-member-holder = link_to "Add new", new_project_team_member_path(@project), :remote => true, :class => "lbutton vm" %table.round-borders#team-table - %tr + %thead %th Name %th Email %th Web diff --git a/app/views/projects/_tree.html.haml b/app/views/projects/_tree.html.haml index 11b04a3b..2aca18e4 100644 --- a/app/views/projects/_tree.html.haml +++ b/app/views/projects/_tree.html.haml @@ -1,31 +1,45 @@ -%h3 - .left - = form_tag tree_project_path(@project), :method => :get do - = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches" -   - .left.prepend-1 - = form_tag tree_project_path(@project), :method => :get do - = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags" - = text_field_tag "ssh", @project.url_to_repo, :class => ["ssh_project_url","one_click_select"] - .clear +.left + = form_tag tree_project_path(@project), :method => :get do + = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches" +.left + = form_tag tree_project_path(@project), :method => :get do + = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags" +.clear + +%br + +-#%a.right.button{:href => "#"} Download +-#-if can? current_user, :admin_project, @project + %a.right.button.blue{:href => "#"} EDIT +#tree-breadcrumbs + %h2.icon + %span + = link_to tree_project_path(@project, :path => nil, :commit_id => @commit.try(:id)), :remote => true, :class => 'project-name' do + %i.arrow> + = @project.name +   + %d + %a{:href => "#"} + = @ref + + - if params[:path] + - part_path = "" + - params[:path].split("\/").each do |part| + - part_path = File.join(part_path, part) unless part_path.empty? + - if part_path.empty? + - part_path = part + \/ + = link_to truncate(part, :length => 40), tree_file_project_path(@project, :path => part_path, :commit_id => @commit.try(:id), :branch => @branch, :tag => @tag), :remote => :true + +.clear -%h3#tree-breadcrumbs - = link_to @project.name, tree_project_path(@project, :path => nil, :commit_id => @commit.try(:id)), :remote => true - - if params[:path] - - part_path = "" - - params[:path].split("\/").each do |part| - - part_path = File.join(part_path, part) unless part_path.empty? - - if part_path.empty? - - part_path = part - \/ - = link_to truncate(part, :length => 40), tree_file_project_path(@project, :path => part_path, :commit_id => @commit.try(:id), :branch => @branch, :tag => @tag), :remote => :true #tree-content-holder - if tree.is_a?(Grit::Blob) = render :partial => "projects/tree_file", :locals => { :name => tree.name, :content => tree.data, :file => tree } - else - contents = tree.contents %table#tree-slider.round-borders - %tr + %thead %th Name %th Last Update %th From 5e12f10c142ca5add14e5c752cf9ef6d88c4dfd8 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Tue, 1 Nov 2011 22:51:20 +0200 Subject: [PATCH 150/176] fixes --- app/views/layouts/_head_panel.html.erb | 6 +- app/views/layouts/devise.html.haml | 3 +- spec/requests/issues_spec.rb | 93 +++++++++++++------ spec/requests/projects_spec.rb | 4 +- spec/support/login.rb | 8 +- .../stylesheets/jquery-ui/jquery-ui.css | 2 +- 6 files changed, 78 insertions(+), 38 deletions(-) diff --git a/app/views/layouts/_head_panel.html.erb b/app/views/layouts/_head_panel.html.erb index e6f36e3f..590e16a2 100644 --- a/app/views/layouts/_head_panel.html.erb +++ b/app/views/layouts/_head_panel.html.erb @@ -10,7 +10,10 @@ <%= current_user.name %> <% end %> <%= link_to 'Logout', destroy_user_session_path, :class => "logout", :method => :delete %> -
      +
      + diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 7bce57e8..bd83bc80 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -62,6 +62,51 @@ describe Project do end end + describe "updates" do + let(:project) { Factory :project } + + before do + @issue = Factory :issue, + :project => project, + :author => Factory(:user), + :assignee => Factory(:user) + + @note = Factory :note, + :project => project, + :author => Factory(:user) + + @commit = project.fresh_commits(1).first + end + + describe "return commit, note & issue" do + it { project.updates(3).count.should == 3 } + it { project.updates(3).last.id.should == @commit.id } + it { project.updates(3).include?(@issue).should be_true } + it { project.updates(3).include?(@note).should be_true } + end + end + + describe "last_activity" do + let(:project) { Factory :project } + + before do + @note = Factory :note, + :project => project, + :author => Factory(:user) + end + + it { project.last_activity.should == @note } + it { project.last_activity_date.to_s.should == @note.created_at.to_s } + end + + describe "fresh commits" do + let(:project) { Factory :project } + + it { project.fresh_commits(3).count.should == 3 } + it { project.fresh_commits.first.id.should == "2fb376f61875b58bceee0492e270e9c805294b1a" } + it { project.fresh_commits.last.id.should == "0dac878dbfe0b9c6104a87d65fe999149a8d862c" } + end + describe "Git methods" do let(:project) { Factory :project } diff --git a/spec/requests/dashboard_spec.rb b/spec/requests/dashboard_spec.rb new file mode 100644 index 00000000..6940366a --- /dev/null +++ b/spec/requests/dashboard_spec.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +describe "Dashboard" do + before { login_as :user } + + describe "GET /dashboard" do + before do + @project = Factory :project + @project.add_access(@user, :read, :write) + visit dashboard_path + end + + it "should be on dashboard page" do + current_path.should == dashboard_path + end + + it "should have projects panel" do + within ".project-list" do + page.should have_content(@project.name) + end + end + + it "should have news feed" do + within "#news-feed" do + page.should have_content(@project.commit.author.name) + page.should have_content(@project.commit.safe_message) + end + end + end +end diff --git a/spec/requests/issues_spec.rb b/spec/requests/issues_spec.rb index 0ff70308..b5d6f1bc 100644 --- a/spec/requests/issues_spec.rb +++ b/spec/requests/issues_spec.rb @@ -105,11 +105,6 @@ describe "Issues" do Notify.should_not_receive(:new_issue_email) click_button "Save" end - - it "should send valid email to user with email & password" do - click_button "Save" - ActionMailer::Base.deliveries.last.should be_nil - end end describe 'assign to other' do From 3abd977822247581465ff6d6df52d2c08e8da508 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 3 Nov 2011 06:56:26 -0400 Subject: [PATCH 154/176] fixed error with ascii error for dashboard --- app/models/issue.rb | 5 +++++ app/models/note.rb | 5 +++++ app/views/commits/_commits.html.haml | 6 +++--- app/views/commits/show.html.haml | 2 +- app/views/dashboard/index.html.haml | 4 ++-- lib/commit_ext.rb | 8 ++++++++ 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/app/models/issue.rb b/app/models/issue.rb index 9fb7ef30..f649cacb 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -10,6 +10,11 @@ class Issue < ActiveRecord::Base validates_presence_of :assignee_id validates_presence_of :author_id + delegate :name, + :email, + :to => :author, + :prefix => true + validates :title, :presence => true, :length => { :within => 0..255 } diff --git a/app/models/note.rb b/app/models/note.rb index 645bc7ce..3c59efef 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -7,6 +7,11 @@ class Note < ActiveRecord::Base belongs_to :author, :class_name => "User" + delegate :name, + :email, + :to => :author, + :prefix => true + attr_protected :author, :author_id validates_presence_of :project diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index 36225d37..9761c65f 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -11,15 +11,15 @@ %i %data.commit-browse{ :onclick => "location.href='#{tree_project_path(@project, :commit_id => commit.id)}';return false;"} Browse Code - - if commit.author.email - = image_tag gravatar_icon(commit.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" + - if commit.author_email + = image_tag gravatar_icon(commit.author_email), :class => "left", :width => 40, :style => "padding-right:5px;" - else = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" %span.commit-title %strong = truncate(commit.safe_message, :length => 60) %span.commit-author - %strong= commit.author + %strong= commit.author_name = time_ago_in_words(commit.committed_date) ago = more_commits_link if @commits.size > 99 diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml index 3227a447..3bd9145e 100644 --- a/app/views/commits/show.html.haml +++ b/app/views/commits/show.html.haml @@ -7,7 +7,7 @@ %td= @commit.id %tr %td Author - %td= @commit.author + %td= @commit.author_name %tr %td Commiter %td= @commit.committer diff --git a/app/views/dashboard/index.html.haml b/app/views/dashboard/index.html.haml index 761826ca..eb2122df 100644 --- a/app/views/dashboard/index.html.haml +++ b/app/views/dashboard/index.html.haml @@ -25,11 +25,11 @@ .data - project.updates.each do |update| %a.project-update{:href => dashboard_feed_path(project, update)} - = image_tag gravatar_icon(update.author.email), :class => "left", :width => 40 + = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40 %span.update-title = dashboard_feed_title(update) %span.update-author - %strong= update.author.name + %strong= update.author_name authored = time_ago_in_words(update.created_at) ago diff --git a/lib/commit_ext.rb b/lib/commit_ext.rb index 32706acb..db650355 100644 --- a/lib/commit_ext.rb +++ b/lib/commit_ext.rb @@ -12,4 +12,12 @@ module CommitExt def created_at committed_date end + + def author_email + author.email.force_encoding(Encoding::UTF_8) + end + + def author_name + author.name.force_encoding(Encoding::UTF_8) + end end From 5c9cb850fcfb7aef6fc595210a11be71c364b2ba Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 3 Nov 2011 07:00:16 -0400 Subject: [PATCH 155/176] dashboard is now root path --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index bac472a2..d45c32bd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -54,5 +54,5 @@ Gitlab::Application.routes.draw do end resources :notes, :only => [:create, :destroy] end - root :to => "projects#index" + root :to => "dashboard#index" end From 5f900772c2a5a1bc86d4e60e1d6b6128b609b96e Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 3 Nov 2011 10:36:02 -0400 Subject: [PATCH 156/176] new favicon --- app/views/layouts/admin.html.haml | 1 - app/views/layouts/application.html.haml | 1 - app/views/layouts/devise.html.haml | 1 - app/views/layouts/profile.html.haml | 1 - app/views/layouts/project.html.haml | 1 - 5 files changed, 5 deletions(-) diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index d3de20da..8df7881c 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -6,7 +6,6 @@ = stylesheet_link_tag "application" = javascript_include_tag "application" = csrf_meta_tags - %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 8cc63253..eedbf116 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -10,7 +10,6 @@ = stylesheet_link_tag "application" = javascript_include_tag "application" = csrf_meta_tags - %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index 968fe58d..32964663 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -6,7 +6,6 @@ = stylesheet_link_tag "application" = javascript_include_tag "application" = csrf_meta_tags - %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index 007e03cf..a33d9d5d 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -6,7 +6,6 @@ = stylesheet_link_tag "application" = javascript_include_tag "application" = csrf_meta_tags - %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index b4b51631..f8d8221a 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -6,7 +6,6 @@ = stylesheet_link_tag "application" = javascript_include_tag "application" = csrf_meta_tags - %link{:href => "/assets/favicon.png", :rel => "icon", :type => "image/png"}/ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; From 3ba392b3cb82a655a814e34759e678cdef94fdfa Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Thu, 3 Nov 2011 12:28:33 -0400 Subject: [PATCH 157/176] new ref switch --- app/assets/images/chosen-sprite.png | Bin 0 -> 396 bytes app/assets/javascripts/chosen.jquery.js | 901 ++++++++++++++++++++++ app/assets/stylesheets/chosen.css | 367 +++++++++ app/assets/stylesheets/projects.css.scss | 13 + app/controllers/application_controller.rb | 20 +- app/helpers/application_helper.rb | 9 + app/views/commits/index.html.haml | 25 +- app/views/projects/_refs.html.haml | 8 + app/views/projects/_tree.html.haml | 21 +- 9 files changed, 1314 insertions(+), 50 deletions(-) create mode 100644 app/assets/images/chosen-sprite.png create mode 100644 app/assets/javascripts/chosen.jquery.js create mode 100644 app/assets/stylesheets/chosen.css create mode 100644 app/views/projects/_refs.html.haml diff --git a/app/assets/images/chosen-sprite.png b/app/assets/images/chosen-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..d08e4b7e624c44f4fb862f23f046262780847490 GIT binary patch literal 396 zcmV;70dxL|P)~c7VWO z{Q}IDn{i!TF4#od;X3Q_#kIK3wRl==hwEDRz~*jyTo-K>u-u(nATT<+akgC{FyDRG qFW$B*q*ia+6;i9W9%5_PVDkwXFTX6NOX?H=0000' + option.html + ''; + } else { + return ""; + } + }; + AbstractChosen.prototype.results_update_field = function() { + this.result_clear_highlight(); + this.result_single_selected = null; + return this.results_build(); + }; + AbstractChosen.prototype.results_toggle = function() { + if (this.results_showing) { + return this.results_hide(); + } else { + return this.results_show(); + } + }; + AbstractChosen.prototype.results_search = function(evt) { + if (this.results_showing) { + return this.winnow_results(); + } else { + return this.results_show(); + } + }; + AbstractChosen.prototype.keyup_checker = function(evt) { + var stroke, _ref; + stroke = (_ref = evt.which) != null ? _ref : evt.keyCode; + this.search_field_scale(); + switch (stroke) { + case 8: + if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) { + return this.keydown_backstroke(); + } else if (!this.pending_backstroke) { + this.result_clear_highlight(); + return this.results_search(); + } + break; + case 13: + evt.preventDefault(); + if (this.results_showing) { + return this.result_select(evt); + } + break; + case 27: + if (this.results_showing) { + return this.results_hide(); + } + break; + case 9: + case 38: + case 40: + case 16: + case 91: + case 17: + break; + default: + return this.results_search(); + } + }; + AbstractChosen.prototype.generate_field_id = function() { + var new_id; + new_id = this.generate_random_id(); + this.form_field.id = new_id; + return new_id; + }; + AbstractChosen.prototype.generate_random_char = function() { + var chars, newchar, rand; + chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ"; + rand = Math.floor(Math.random() * chars.length); + return newchar = chars.substring(rand, rand + 1); + }; + return AbstractChosen; + })(); + root.AbstractChosen = AbstractChosen; +}).call(this); +(function() { + /* + Chosen source: generate output using 'cake build' + Copyright (c) 2011 by Harvest + */ + var $, Chosen, get_side_border_padding, root; + var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { + for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor; + child.__super__ = parent.prototype; + return child; + }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; + root = this; + $ = jQuery; + $.fn.extend({ + chosen: function(options) { + if ($.browser.msie && ($.browser.version === "6.0" || $.browser.version === "7.0")) { + return this; + } + return $(this).each(function(input_field) { + if (!($(this)).hasClass("chzn-done")) { + return new Chosen(this, options); + } + }); + } + }); + Chosen = (function() { + __extends(Chosen, AbstractChosen); + function Chosen() { + Chosen.__super__.constructor.apply(this, arguments); + } + Chosen.prototype.setup = function() { + this.form_field_jq = $(this.form_field); + return this.is_rtl = this.form_field_jq.hasClass("chzn-rtl"); + }; + Chosen.prototype.finish_setup = function() { + return this.form_field_jq.addClass("chzn-done"); + }; + Chosen.prototype.set_up_html = function() { + var container_div, dd_top, dd_width, sf_width; + this.container_id = this.form_field.id.length ? this.form_field.id.replace(/(:|\.)/g, '_') : this.generate_field_id(); + this.container_id += "_chzn"; + this.f_width = this.form_field_jq.outerWidth(); + this.default_text = this.form_field_jq.data('placeholder') ? this.form_field_jq.data('placeholder') : this.default_text_default; + container_div = $("
      ", { + id: this.container_id, + "class": "chzn-container" + (this.is_rtl ? ' chzn-rtl' : ''), + style: 'width: ' + this.f_width + 'px;' + }); + if (this.is_multiple) { + container_div.html('
        '); + } else { + container_div.html('' + this.default_text + '
          '); + } + this.form_field_jq.hide().after(container_div); + this.container = $('#' + this.container_id); + this.container.addClass("chzn-container-" + (this.is_multiple ? "multi" : "single")); + this.dropdown = this.container.find('div.chzn-drop').first(); + dd_top = this.container.height(); + dd_width = this.f_width - get_side_border_padding(this.dropdown); + this.dropdown.css({ + "width": dd_width + "px", + "top": dd_top + "px" + }); + this.search_field = this.container.find('input').first(); + this.search_results = this.container.find('ul.chzn-results').first(); + this.search_field_scale(); + this.search_no_results = this.container.find('li.no-results').first(); + if (this.is_multiple) { + this.search_choices = this.container.find('ul.chzn-choices').first(); + this.search_container = this.container.find('li.search-field').first(); + } else { + this.search_container = this.container.find('div.chzn-search').first(); + this.selected_item = this.container.find('.chzn-single').first(); + sf_width = dd_width - get_side_border_padding(this.search_container) - get_side_border_padding(this.search_field); + this.search_field.css({ + "width": sf_width + "px" + }); + } + this.results_build(); + this.set_tab_index(); + return this.form_field_jq.trigger("liszt:ready", { + chosen: this + }); + }; + Chosen.prototype.register_observers = function() { + this.container.mousedown(__bind(function(evt) { + return this.container_mousedown(evt); + }, this)); + this.container.mouseup(__bind(function(evt) { + return this.container_mouseup(evt); + }, this)); + this.container.mouseenter(__bind(function(evt) { + return this.mouse_enter(evt); + }, this)); + this.container.mouseleave(__bind(function(evt) { + return this.mouse_leave(evt); + }, this)); + this.search_results.mouseup(__bind(function(evt) { + return this.search_results_mouseup(evt); + }, this)); + this.search_results.mouseover(__bind(function(evt) { + return this.search_results_mouseover(evt); + }, this)); + this.search_results.mouseout(__bind(function(evt) { + return this.search_results_mouseout(evt); + }, this)); + this.form_field_jq.bind("liszt:updated", __bind(function(evt) { + return this.results_update_field(evt); + }, this)); + this.search_field.blur(__bind(function(evt) { + return this.input_blur(evt); + }, this)); + this.search_field.keyup(__bind(function(evt) { + return this.keyup_checker(evt); + }, this)); + this.search_field.keydown(__bind(function(evt) { + return this.keydown_checker(evt); + }, this)); + if (this.is_multiple) { + this.search_choices.click(__bind(function(evt) { + return this.choices_click(evt); + }, this)); + return this.search_field.focus(__bind(function(evt) { + return this.input_focus(evt); + }, this)); + } + }; + Chosen.prototype.search_field_disabled = function() { + this.is_disabled = this.form_field_jq[0].disabled; + if (this.is_disabled) { + this.container.addClass('chzn-disabled'); + this.search_field[0].disabled = true; + if (!this.is_multiple) { + this.selected_item.unbind("focus", this.activate_action); + } + return this.close_field(); + } else { + this.container.removeClass('chzn-disabled'); + this.search_field[0].disabled = false; + if (!this.is_multiple) { + return this.selected_item.bind("focus", this.activate_action); + } + } + }; + Chosen.prototype.container_mousedown = function(evt) { + var target_closelink; + if (!this.is_disabled) { + target_closelink = evt != null ? ($(evt.target)).hasClass("search-choice-close") : false; + if (evt && evt.type === "mousedown") { + evt.stopPropagation(); + } + if (!this.pending_destroy_click && !target_closelink) { + if (!this.active_field) { + if (this.is_multiple) { + this.search_field.val(""); + } + $(document).click(this.click_test_action); + this.results_show(); + } else if (!this.is_multiple && evt && ($(evt.target) === this.selected_item || $(evt.target).parents("a.chzn-single").length)) { + evt.preventDefault(); + this.results_toggle(); + } + return this.activate_field(); + } else { + return this.pending_destroy_click = false; + } + } + }; + Chosen.prototype.container_mouseup = function(evt) { + if (evt.target.nodeName === "ABBR") { + return this.results_reset(evt); + } + }; + Chosen.prototype.blur_test = function(evt) { + if (!this.active_field && this.container.hasClass("chzn-container-active")) { + return this.close_field(); + } + }; + Chosen.prototype.close_field = function() { + $(document).unbind("click", this.click_test_action); + if (!this.is_multiple) { + this.selected_item.attr("tabindex", this.search_field.attr("tabindex")); + this.search_field.attr("tabindex", -1); + } + this.active_field = false; + this.results_hide(); + this.container.removeClass("chzn-container-active"); + this.winnow_results_clear(); + this.clear_backstroke(); + this.show_search_field_default(); + return this.search_field_scale(); + }; + Chosen.prototype.activate_field = function() { + if (!this.is_multiple && !this.active_field) { + this.search_field.attr("tabindex", this.selected_item.attr("tabindex")); + this.selected_item.attr("tabindex", -1); + } + this.container.addClass("chzn-container-active"); + this.active_field = true; + this.search_field.val(this.search_field.val()); + return this.search_field.focus(); + }; + Chosen.prototype.test_active_click = function(evt) { + if ($(evt.target).parents('#' + this.container_id).length) { + return this.active_field = true; + } else { + return this.close_field(); + } + }; + Chosen.prototype.results_build = function() { + var content, data, startTime, _i, _len, _ref; + startTime = new Date(); + this.parsing = true; + this.results_data = root.SelectParser.select_to_array(this.form_field); + if (this.is_multiple && this.choices > 0) { + this.search_choices.find("li.search-choice").remove(); + this.choices = 0; + } else if (!this.is_multiple) { + this.selected_item.find("span").text(this.default_text); + if (this.form_field.options.length <= this.disable_search_threshold) { + this.container.addClass("chzn-container-single-nosearch"); + } else { + this.container.removeClass("chzn-container-single-nosearch"); + } + } + content = ''; + _ref = this.results_data; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + data = _ref[_i]; + if (data.group) { + content += this.result_add_group(data); + } else if (!data.empty) { + content += this.result_add_option(data); + if (data.selected && this.is_multiple) { + this.choice_build(data); + } else if (data.selected && !this.is_multiple) { + this.selected_item.find("span").text(data.text); + if (this.allow_single_deselect) { + this.single_deselect_control_build(); + } + } + } + } + this.search_field_disabled(); + this.show_search_field_default(); + this.search_field_scale(); + this.search_results.html(content); + return this.parsing = false; + }; + Chosen.prototype.result_add_group = function(group) { + if (!group.disabled) { + group.dom_id = this.container_id + "_g_" + group.array_index; + return '
        • ' + $("
          ").text(group.label).html() + '
        • '; + } else { + return ""; + } + }; + Chosen.prototype.result_do_highlight = function(el) { + var high_bottom, high_top, maxHeight, visible_bottom, visible_top; + if (el.length) { + this.result_clear_highlight(); + this.result_highlight = el; + this.result_highlight.addClass("highlighted"); + maxHeight = parseInt(this.search_results.css("maxHeight"), 10); + visible_top = this.search_results.scrollTop(); + visible_bottom = maxHeight + visible_top; + high_top = this.result_highlight.position().top + this.search_results.scrollTop(); + high_bottom = high_top + this.result_highlight.outerHeight(); + if (high_bottom >= visible_bottom) { + return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0); + } else if (high_top < visible_top) { + return this.search_results.scrollTop(high_top); + } + } + }; + Chosen.prototype.result_clear_highlight = function() { + if (this.result_highlight) { + this.result_highlight.removeClass("highlighted"); + } + return this.result_highlight = null; + }; + Chosen.prototype.results_show = function() { + var dd_top; + if (!this.is_multiple) { + this.selected_item.addClass("chzn-single-with-drop"); + if (this.result_single_selected) { + this.result_do_highlight(this.result_single_selected); + } + } + dd_top = this.is_multiple ? this.container.height() : this.container.height() - 1; + this.dropdown.css({ + "top": dd_top + "px", + "left": 0 + }); + this.results_showing = true; + this.search_field.focus(); + this.search_field.val(this.search_field.val()); + return this.winnow_results(); + }; + Chosen.prototype.results_hide = function() { + if (!this.is_multiple) { + this.selected_item.removeClass("chzn-single-with-drop"); + } + this.result_clear_highlight(); + this.dropdown.css({ + "left": "-9000px" + }); + return this.results_showing = false; + }; + Chosen.prototype.set_tab_index = function(el) { + var ti; + if (this.form_field_jq.attr("tabindex")) { + ti = this.form_field_jq.attr("tabindex"); + this.form_field_jq.attr("tabindex", -1); + if (this.is_multiple) { + return this.search_field.attr("tabindex", ti); + } else { + this.selected_item.attr("tabindex", ti); + return this.search_field.attr("tabindex", -1); + } + } + }; + Chosen.prototype.show_search_field_default = function() { + if (this.is_multiple && this.choices < 1 && !this.active_field) { + this.search_field.val(this.default_text); + return this.search_field.addClass("default"); + } else { + this.search_field.val(""); + return this.search_field.removeClass("default"); + } + }; + Chosen.prototype.search_results_mouseup = function(evt) { + var target; + target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); + if (target.length) { + this.result_highlight = target; + return this.result_select(evt); + } + }; + Chosen.prototype.search_results_mouseover = function(evt) { + var target; + target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first(); + if (target) { + return this.result_do_highlight(target); + } + }; + Chosen.prototype.search_results_mouseout = function(evt) { + if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) { + return this.result_clear_highlight(); + } + }; + Chosen.prototype.choices_click = function(evt) { + evt.preventDefault(); + if (this.active_field && !($(evt.target).hasClass("search-choice" || $(evt.target).parents('.search-choice').first)) && !this.results_showing) { + return this.results_show(); + } + }; + Chosen.prototype.choice_build = function(item) { + var choice_id, link; + choice_id = this.container_id + "_c_" + item.array_index; + this.choices += 1; + this.search_container.before('
        • ' + item.html + '
        • '); + link = $('#' + choice_id).find("a").first(); + return link.click(__bind(function(evt) { + return this.choice_destroy_link_click(evt); + }, this)); + }; + Chosen.prototype.choice_destroy_link_click = function(evt) { + evt.preventDefault(); + if (!this.is_disabled) { + this.pending_destroy_click = true; + return this.choice_destroy($(evt.target)); + } else { + return evt.stopPropagation; + } + }; + Chosen.prototype.choice_destroy = function(link) { + this.choices -= 1; + this.show_search_field_default(); + if (this.is_multiple && this.choices > 0 && this.search_field.val().length < 1) { + this.results_hide(); + } + this.result_deselect(link.attr("rel")); + return link.parents('li').first().remove(); + }; + Chosen.prototype.results_reset = function(evt) { + this.form_field.options[0].selected = true; + this.selected_item.find("span").text(this.default_text); + this.show_search_field_default(); + $(evt.target).remove(); + this.form_field_jq.trigger("change"); + if (this.active_field) { + return this.results_hide(); + } + }; + Chosen.prototype.result_select = function(evt) { + var high, high_id, item, position; + if (this.result_highlight) { + high = this.result_highlight; + high_id = high.attr("id"); + this.result_clear_highlight(); + if (this.is_multiple) { + this.result_deactivate(high); + } else { + this.search_results.find(".result-selected").removeClass("result-selected"); + this.result_single_selected = high; + } + high.addClass("result-selected"); + position = high_id.substr(high_id.lastIndexOf("_") + 1); + item = this.results_data[position]; + item.selected = true; + this.form_field.options[item.options_index].selected = true; + if (this.is_multiple) { + this.choice_build(item); + } else { + this.selected_item.find("span").first().text(item.text); + if (this.allow_single_deselect) { + this.single_deselect_control_build(); + } + } + if (!(evt.metaKey && this.is_multiple)) { + this.results_hide(); + } + this.search_field.val(""); + this.form_field_jq.trigger("change"); + return this.search_field_scale(); + } + }; + Chosen.prototype.result_activate = function(el) { + return el.addClass("active-result"); + }; + Chosen.prototype.result_deactivate = function(el) { + return el.removeClass("active-result"); + }; + Chosen.prototype.result_deselect = function(pos) { + var result, result_data; + result_data = this.results_data[pos]; + result_data.selected = false; + this.form_field.options[result_data.options_index].selected = false; + result = $("#" + this.container_id + "_o_" + pos); + result.removeClass("result-selected").addClass("active-result").show(); + this.result_clear_highlight(); + this.winnow_results(); + this.form_field_jq.trigger("change"); + return this.search_field_scale(); + }; + Chosen.prototype.single_deselect_control_build = function() { + if (this.allow_single_deselect && this.selected_item.find("abbr").length < 1) { + return this.selected_item.find("span").first().after(""); + } + }; + Chosen.prototype.winnow_results = function() { + var found, option, part, parts, regex, result_id, results, searchText, startTime, startpos, text, zregex, _i, _j, _len, _len2, _ref; + startTime = new Date(); + this.no_results_clear(); + results = 0; + searchText = this.search_field.val() === this.default_text ? "" : $('
          ').text($.trim(this.search_field.val())).html(); + regex = new RegExp('^' + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'); + zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i'); + _ref = this.results_data; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + option = _ref[_i]; + if (!option.disabled && !option.empty) { + if (option.group) { + $('#' + option.dom_id).hide(); + } else if (!(this.is_multiple && option.selected)) { + found = false; + result_id = option.dom_id; + if (regex.test(option.html)) { + found = true; + results += 1; + } else if (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0) { + parts = option.html.replace(/\[|\]/g, "").split(" "); + if (parts.length) { + for (_j = 0, _len2 = parts.length; _j < _len2; _j++) { + part = parts[_j]; + if (regex.test(part)) { + found = true; + results += 1; + } + } + } + } + if (found) { + if (searchText.length) { + startpos = option.html.search(zregex); + text = option.html.substr(0, startpos + searchText.length) + '' + option.html.substr(startpos + searchText.length); + text = text.substr(0, startpos) + '' + text.substr(startpos); + } else { + text = option.html; + } + if ($("#" + result_id).html !== text) { + $("#" + result_id).html(text); + } + this.result_activate($("#" + result_id)); + if (option.group_array_index != null) { + $("#" + this.results_data[option.group_array_index].dom_id).show(); + } + } else { + if (this.result_highlight && result_id === this.result_highlight.attr('id')) { + this.result_clear_highlight(); + } + this.result_deactivate($("#" + result_id)); + } + } + } + } + if (results < 1 && searchText.length) { + return this.no_results(searchText); + } else { + return this.winnow_results_set_highlight(); + } + }; + Chosen.prototype.winnow_results_clear = function() { + var li, lis, _i, _len, _results; + this.search_field.val(""); + lis = this.search_results.find("li"); + _results = []; + for (_i = 0, _len = lis.length; _i < _len; _i++) { + li = lis[_i]; + li = $(li); + _results.push(li.hasClass("group-result") ? li.show() : !this.is_multiple || !li.hasClass("result-selected") ? this.result_activate(li) : void 0); + } + return _results; + }; + Chosen.prototype.winnow_results_set_highlight = function() { + var do_high, selected_results; + if (!this.result_highlight) { + selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : []; + do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first(); + if (do_high != null) { + return this.result_do_highlight(do_high); + } + } + }; + Chosen.prototype.no_results = function(terms) { + var no_results_html; + no_results_html = $('
        • ' + this.results_none_found + ' ""
        • '); + no_results_html.find("span").first().html(terms); + return this.search_results.append(no_results_html); + }; + Chosen.prototype.no_results_clear = function() { + return this.search_results.find(".no-results").remove(); + }; + Chosen.prototype.keydown_arrow = function() { + var first_active, next_sib; + if (!this.result_highlight) { + first_active = this.search_results.find("li.active-result").first(); + if (first_active) { + this.result_do_highlight($(first_active)); + } + } else if (this.results_showing) { + next_sib = this.result_highlight.nextAll("li.active-result").first(); + if (next_sib) { + this.result_do_highlight(next_sib); + } + } + if (!this.results_showing) { + return this.results_show(); + } + }; + Chosen.prototype.keyup_arrow = function() { + var prev_sibs; + if (!this.results_showing && !this.is_multiple) { + return this.results_show(); + } else if (this.result_highlight) { + prev_sibs = this.result_highlight.prevAll("li.active-result"); + if (prev_sibs.length) { + return this.result_do_highlight(prev_sibs.first()); + } else { + if (this.choices > 0) { + this.results_hide(); + } + return this.result_clear_highlight(); + } + } + }; + Chosen.prototype.keydown_backstroke = function() { + if (this.pending_backstroke) { + this.choice_destroy(this.pending_backstroke.find("a").first()); + return this.clear_backstroke(); + } else { + this.pending_backstroke = this.search_container.siblings("li.search-choice").last(); + return this.pending_backstroke.addClass("search-choice-focus"); + } + }; + Chosen.prototype.clear_backstroke = function() { + if (this.pending_backstroke) { + this.pending_backstroke.removeClass("search-choice-focus"); + } + return this.pending_backstroke = null; + }; + Chosen.prototype.keydown_checker = function(evt) { + var stroke, _ref; + stroke = (_ref = evt.which) != null ? _ref : evt.keyCode; + this.search_field_scale(); + if (stroke !== 8 && this.pending_backstroke) { + this.clear_backstroke(); + } + switch (stroke) { + case 8: + this.backstroke_length = this.search_field.val().length; + break; + case 9: + if (this.results_showing && !this.is_multiple) { + this.result_select(evt); + } + this.mouse_on_container = false; + break; + case 13: + evt.preventDefault(); + break; + case 38: + evt.preventDefault(); + this.keyup_arrow(); + break; + case 40: + this.keydown_arrow(); + break; + } + }; + Chosen.prototype.search_field_scale = function() { + var dd_top, div, h, style, style_block, styles, w, _i, _len; + if (this.is_multiple) { + h = 0; + w = 0; + style_block = "position:absolute; left: -1000px; top: -1000px; display:none;"; + styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing']; + for (_i = 0, _len = styles.length; _i < _len; _i++) { + style = styles[_i]; + style_block += style + ":" + this.search_field.css(style) + ";"; + } + div = $('
          ', { + 'style': style_block + }); + div.text(this.search_field.val()); + $('body').append(div); + w = div.width() + 25; + div.remove(); + if (w > this.f_width - 10) { + w = this.f_width - 10; + } + this.search_field.css({ + 'width': w + 'px' + }); + dd_top = this.container.height(); + return this.dropdown.css({ + "top": dd_top + "px" + }); + } + }; + Chosen.prototype.generate_random_id = function() { + var string; + string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char(); + while ($("#" + string).length > 0) { + string += this.generate_random_char(); + } + return string; + }; + return Chosen; + })(); + get_side_border_padding = function(elmt) { + var side_border_padding; + return side_border_padding = elmt.outerWidth() - elmt.width(); + }; + root.get_side_border_padding = get_side_border_padding; +}).call(this); diff --git a/app/assets/stylesheets/chosen.css b/app/assets/stylesheets/chosen.css new file mode 100644 index 00000000..7870f053 --- /dev/null +++ b/app/assets/stylesheets/chosen.css @@ -0,0 +1,367 @@ +/* @group Base */ +.chzn-container { + font-size: 13px; + position: relative; + display: inline-block; + zoom: 1; + *display: inline; +} +.chzn-container .chzn-drop { + background: #fff; + border: 1px solid #aaa; + border-top: 0; + position: absolute; + top: 29px; + left: 0; + -webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15); + -moz-box-shadow : 0 4px 5px rgba(0,0,0,.15); + -o-box-shadow : 0 4px 5px rgba(0,0,0,.15); + box-shadow : 0 4px 5px rgba(0,0,0,.15); + z-index: 999; +} +/* @end */ + +/* @group Single Chosen */ +.chzn-container-single .chzn-single { + background-color: #fff; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white)); + background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%); + background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 50%); + background-image: -o-linear-gradient(top, #eeeeee 0%,#ffffff 50%); + background-image: -ms-linear-gradient(top, #eeeeee 0%,#ffffff 50%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 ); + background-image: linear-gradient(top, #eeeeee 0%,#ffffff 50%); + -webkit-border-radius: 4px; + -moz-border-radius : 4px; + border-radius : 4px; + -moz-background-clip : padding; + -webkit-background-clip: padding-box; + background-clip : padding-box; + border: 1px solid #aaa; + display: block; + overflow: hidden; + white-space: nowrap; + position: relative; + height: 26px; + line-height: 26px; + padding: 0 0 0 8px; + color: #444; + text-decoration: none; +} +.chzn-container-single .chzn-single span { + margin-right: 26px; + display: block; + overflow: hidden; + white-space: nowrap; + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; + text-overflow: ellipsis; +} +.chzn-container-single .chzn-single abbr { + display: block; + position: absolute; + right: 26px; + top: 8px; + width: 12px; + height: 13px; + font-size: 1px; + background: url(chosen-sprite.png) right top no-repeat; +} +.chzn-container-single .chzn-single abbr:hover { + background-position: right -11px; +} +.chzn-container-single .chzn-single div { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius : 0 4px 4px 0; + border-radius : 0 4px 4px 0; + -moz-background-clip : padding; + -webkit-background-clip: padding-box; + background-clip : padding-box; + background: #ccc; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); + background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%); + background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%); + background-image: -o-linear-gradient(bottom, #ccc 0%, #eee 60%); + background-image: -ms-linear-gradient(top, #cccccc 0%,#eeeeee 60%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#cccccc', endColorstr='#eeeeee',GradientType=0 ); + background-image: linear-gradient(top, #cccccc 0%,#eeeeee 60%); + border-left: 1px solid #aaa; + position: absolute; + right: 0; + top: 0; + display: block; + height: 100%; + width: 18px; +} +.chzn-container-single .chzn-single div b { + background: url('chosen-sprite.png') no-repeat 0 1px; + display: block; + width: 100%; + height: 100%; +} +.chzn-container-single .chzn-search { + padding: 3px 4px; + position: relative; + margin: 0; + white-space: nowrap; + z-index: 1010; +} +.chzn-container-single .chzn-search input { + background: #fff url('chosen-sprite.png') no-repeat 100% -22px; + background: url('chosen-sprite.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background: url('chosen-sprite.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); + background: url('chosen-sprite.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%,#eeeeee 99%); + margin: 1px 0; + padding: 4px 20px 4px 5px; + outline: 0; + border: 1px solid #aaa; + font-family: sans-serif; + font-size: 1em; +} +.chzn-container-single .chzn-drop { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius : 0 0 4px 4px; + border-radius : 0 0 4px 4px; + -moz-background-clip : padding; + -webkit-background-clip: padding-box; + background-clip : padding-box; +} +/* @end */ + +.chzn-container-single-nosearch .chzn-search input { + position: absolute; + left: -9000px; +} + +/* @group Multi Chosen */ +.chzn-container-multi .chzn-choices { + background-color: #fff; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background-image: -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background-image: -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background-image: -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background-image: -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 ); + background-image: linear-gradient(top, #ffffff 85%,#eeeeee 99%); + border: 1px solid #aaa; + margin: 0; + padding: 0; + cursor: text; + overflow: hidden; + height: auto !important; + height: 1%; + position: relative; +} +.chzn-container-multi .chzn-choices li { + float: left; + list-style: none; +} +.chzn-container-multi .chzn-choices .search-field { + white-space: nowrap; + margin: 0; + padding: 0; +} +.chzn-container-multi .chzn-choices .search-field input { + color: #666; + background: transparent !important; + border: 0 !important; + padding: 5px; + margin: 1px 0; + outline: 0; + -webkit-box-shadow: none; + -moz-box-shadow : none; + -o-box-shadow : none; + box-shadow : none; +} +.chzn-container-multi .chzn-choices .search-field .default { + color: #999; +} +.chzn-container-multi .chzn-choices .search-choice { + -webkit-border-radius: 3px; + -moz-border-radius : 3px; + border-radius : 3px; + -moz-background-clip : padding; + -webkit-background-clip: padding-box; + background-clip : padding-box; + background-color: #e4e4e4; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #e4e4e4), color-stop(0.7, #eeeeee)); + background-image: -webkit-linear-gradient(center bottom, #e4e4e4 0%, #eeeeee 70%); + background-image: -moz-linear-gradient(center bottom, #e4e4e4 0%, #eeeeee 70%); + background-image: -o-linear-gradient(bottom, #e4e4e4 0%, #eeeeee 70%); + background-image: -ms-linear-gradient(top, #e4e4e4 0%,#eeeeee 70%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#e4e4e4', endColorstr='#eeeeee',GradientType=0 ); + background-image: linear-gradient(top, #e4e4e4 0%,#eeeeee 70%); + color: #333; + border: 1px solid #b4b4b4; + line-height: 13px; + padding: 3px 19px 3px 6px; + margin: 3px 0 3px 5px; + position: relative; +} +.chzn-container-multi .chzn-choices .search-choice span { + cursor: default; +} +.chzn-container-multi .chzn-choices .search-choice-focus { + background: #d4d4d4; +} +.chzn-container-multi .chzn-choices .search-choice .search-choice-close { + display: block; + position: absolute; + right: 3px; + top: 4px; + width: 12px; + height: 13px; + font-size: 1px; + background: url(chosen-sprite.png) right top no-repeat; +} +.chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover { + background-position: right -11px; +} +.chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close { + background-position: right -11px; +} +/* @end */ + +/* @group Results */ +.chzn-container .chzn-results { + margin: 0 4px 4px 0; + max-height: 190px; + padding: 0 0 0 4px; + position: relative; + overflow-x: hidden; + overflow-y: auto; +} +.chzn-container-multi .chzn-results { + margin: -1px 0 0; + padding: 0; +} +.chzn-container .chzn-results li { + display: none; + line-height: 80%; + padding: 7px 7px 8px; + margin: 0; + list-style: none; +} +.chzn-container .chzn-results .active-result { + cursor: pointer; + display: list-item; +} +.chzn-container .chzn-results .highlighted { + background: #3875d7; + color: #fff; +} +.chzn-container .chzn-results li em { + background: #feffde; + font-style: normal; +} +.chzn-container .chzn-results .highlighted em { + background: transparent; +} +.chzn-container .chzn-results .no-results { + background: #f4f4f4; + display: list-item; +} +.chzn-container .chzn-results .group-result { + cursor: default; + color: #999; + font-weight: bold; +} +.chzn-container .chzn-results .group-option { + padding-left: 20px; +} +.chzn-container-multi .chzn-drop .result-selected { + display: none; +} +/* @end */ + +/* @group Active */ +.chzn-container-active .chzn-single { + -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); + -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); + -o-box-shadow : 0 0 5px rgba(0,0,0,.3); + box-shadow : 0 0 5px rgba(0,0,0,.3); + border: 1px solid #5897fb; +} +.chzn-container-active .chzn-single-with-drop { + border: 1px solid #aaa; + -webkit-box-shadow: 0 1px 0 #fff inset; + -moz-box-shadow : 0 1px 0 #fff inset; + -o-box-shadow : 0 1px 0 #fff inset; + box-shadow : 0 1px 0 #fff inset; + background-color: #eee; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, white), color-stop(0.5, #eeeeee)); + background-image: -webkit-linear-gradient(center bottom, white 0%, #eeeeee 50%); + background-image: -moz-linear-gradient(center bottom, white 0%, #eeeeee 50%); + background-image: -o-linear-gradient(bottom, white 0%, #eeeeee 50%); + background-image: -ms-linear-gradient(top, #ffffff 0%,#eeeeee 50%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 ); + background-image: linear-gradient(top, #ffffff 0%,#eeeeee 50%); + -webkit-border-bottom-left-radius : 0; + -webkit-border-bottom-right-radius: 0; + -moz-border-radius-bottomleft : 0; + -moz-border-radius-bottomright: 0; + border-bottom-left-radius : 0; + border-bottom-right-radius: 0; +} +.chzn-container-active .chzn-single-with-drop div { + background: transparent; + border-left: none; +} +.chzn-container-active .chzn-single-with-drop div b { + background-position: -18px 1px; +} +.chzn-container-active .chzn-choices { + -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); + -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); + -o-box-shadow : 0 0 5px rgba(0,0,0,.3); + box-shadow : 0 0 5px rgba(0,0,0,.3); + border: 1px solid #5897fb; +} +.chzn-container-active .chzn-choices .search-field input { + color: #111 !important; +} +/* @end */ + +/* @group Disabled Support */ +.chzn-disabled { + cursor: default; + opacity:0.5 !important; +} +.chzn-disabled .chzn-single { + cursor: default; +} +.chzn-disabled .chzn-choices .search-choice .search-choice-close { + cursor: default; +} + +/* @group Right to Left */ +.chzn-rtl { direction:rtl;text-align: right; } +.chzn-rtl .chzn-single { padding-left: 0; padding-right: 8px; } +.chzn-rtl .chzn-single span { margin-left: 26px; margin-right: 0; } +.chzn-rtl .chzn-single div { + left: 0; right: auto; + border-left: none; border-right: 1px solid #aaaaaa; + -webkit-border-radius: 4px 0 0 4px; + -moz-border-radius : 4px 0 0 4px; + border-radius : 4px 0 0 4px; +} +.chzn-rtl .chzn-choices li { float: right; } +.chzn-rtl .chzn-choices .search-choice { padding: 3px 6px 3px 19px; margin: 3px 5px 3px 0; } +.chzn-rtl .chzn-choices .search-choice .search-choice-close { left: 5px; right: auto; background-position: right top;} +.chzn-rtl.chzn-container-single .chzn-results { margin-left: 4px; margin-right: 0; padding-left: 0; padding-right: 4px; } +.chzn-rtl .chzn-results .group-option { padding-left: 0; padding-right: 20px; } +.chzn-rtl.chzn-container-active .chzn-single-with-drop div { border-right: none; } +.chzn-rtl .chzn-search input { + background: url('chosen-sprite.png') no-repeat -38px -22px, #ffffff; + background: url('chosen-sprite.png') no-repeat -38px -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background: url('chosen-sprite.png') no-repeat -38px -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, -ms-linear-gradient(top, #ffffff 85%,#eeeeee 99%); + background: url('chosen-sprite.png') no-repeat -38px -22px, linear-gradient(top, #ffffff 85%,#eeeeee 99%); + padding: 4px 5px 4px 20px; +} +/* @end */ diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index d8e04318..4e4bcccc 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -706,3 +706,16 @@ table.highlighttable pre{ line-height:16px !important; font-size:12px !important; } + +.project-refs-form { + span { + background: none !important; + position:static !important; + width:auto !important; + height: auto !important; + } +} + +.project-refs-select { + width:200px; +} diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0bf38a57..6d0edace 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -57,19 +57,13 @@ class ApplicationController < ActionController::Base end def load_refs - @branch = unless params[:branch].blank? - params[:branch] - else - nil - end - - @tag = unless params[:tag].blank? - params[:tag] - else - nil - end - - @ref = @branch || @tag || "master" + unless params[:ref].blank? + @ref = params[:ref] + else + @branch = params[:branch].blank? ? nil : params[:branch] + @tag = params[:tag].blank? ? nil : params[:tag] + @ref = @branch || @tag || "master" + end end def render_404 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ef92953d..3aa40c99 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -32,6 +32,15 @@ module ApplicationHelper "Never" end + def grouped_options_refs + options = [ + ["Branch", @repo.heads.map(&:name) ], + [ "Tag", @project.tags ] + ] + + grouped_options_for_select(options, @ref) + end + def markdown(text) RDiscount.new(text, :autolink, :no_pseudo_protocols, :safelink, :smart, :filter_html).to_html.html_safe end diff --git a/app/views/commits/index.html.haml b/app/views/commits/index.html.haml index f8928b6f..7999b94c 100644 --- a/app/views/commits/index.html.haml +++ b/app/views/commits/index.html.haml @@ -1,33 +1,18 @@ - content_for(:body_class, "project-page commits-page") -.left - = form_tag project_commits_path(@project), :method => :get do - = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches" -.left - = form_tag project_commits_path(@project), :method => :get do - = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags" -.clear - -%br - - -#%a.right.button{:href => "#"} Download -#-if can? current_user, :admin_project, @project %a.right.button.blue{:href => "#"} EDIT %h2.icon %span - %a.project-name{:href => "#"} - %i.arrow> - Project -   %d - %a{:href => "#"} - = @ref - - if params[:path] -   - %d + = link_to project_commits_path(@project) do + = @project.name + - if params[:path] + \/ %a{:href => "#"}= params[:path].split("/").join(" / ") +.right= render "projects/refs" %div{:id => dom_id(@project)} = render "commits" diff --git a/app/views/projects/_refs.html.haml b/app/views/projects/_refs.html.haml new file mode 100644 index 00000000..f7712d3d --- /dev/null +++ b/app/views/projects/_refs.html.haml @@ -0,0 +1,8 @@ += form_tag project_commits_path(@project), :method => :get, :class => "project-refs-form" do + = select_tag "ref", grouped_options_refs, :onchange => "this.form.submit();", :class => "project-refs-select" + + +:javascript + $(function(){ + $('.project-refs-select').chosen(); + }) diff --git a/app/views/projects/_tree.html.haml b/app/views/projects/_tree.html.haml index 2aca18e4..f70bbb7a 100644 --- a/app/views/projects/_tree.html.haml +++ b/app/views/projects/_tree.html.haml @@ -1,12 +1,3 @@ -.left - = form_tag tree_project_path(@project), :method => :get do - = select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "", :prompt => "Branches" -.left - = form_tag tree_project_path(@project), :method => :get do - = select_tag "tag", options_for_select(@project.tags, @tag), :onchange => "this.form.submit();", :class => "", :prompt => "Tags" -.clear - -%br -#%a.right.button{:href => "#"} Download -#-if can? current_user, :admin_project, @project @@ -14,14 +5,9 @@ #tree-breadcrumbs %h2.icon %span - = link_to tree_project_path(@project, :path => nil, :commit_id => @commit.try(:id)), :remote => true, :class => 'project-name' do - %i.arrow> - = @project.name -   %d - %a{:href => "#"} - = @ref - + = link_to tree_project_path(@project, :path => nil, :commit_id => @commit.try(:id)), :remote => true do + = @project.name - if params[:path] - part_path = "" - params[:path].split("\/").each do |part| @@ -30,7 +16,8 @@ - part_path = part \/ = link_to truncate(part, :length => 40), tree_file_project_path(@project, :path => part_path, :commit_id => @commit.try(:id), :branch => @branch, :tag => @tag), :remote => :true - +   + .right= render "projects/refs" .clear #tree-content-holder From a9639776d7c52ca63c5ca7b86baf300b1a5e87e8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 4 Nov 2011 00:37:02 +0200 Subject: [PATCH 158/176] fixed/fluid layout switch --- app/assets/stylesheets/style.scss | 2 +- app/controllers/application_controller.rb | 10 +++++ app/helpers/application_helper.rb | 8 ++++ app/views/layouts/_head_panel.html.erb | 51 +++++++++++------------ app/views/layouts/admin.html.haml | 2 +- app/views/layouts/application.html.haml | 2 +- app/views/layouts/profile.html.haml | 2 +- app/views/layouts/project.html.haml | 2 +- 8 files changed, 47 insertions(+), 32 deletions(-) diff --git a/app/assets/stylesheets/style.scss b/app/assets/stylesheets/style.scss index 97be566f..29e6058d 100755 --- a/app/assets/stylesheets/style.scss +++ b/app/assets/stylesheets/style.scss @@ -292,7 +292,7 @@ body.login-page{background-color: #f1f1f1; padding-top: 10%} /* General */ #container{background-color: white; overflow: hidden;} -/*#container{margin: auto; width: 980px; border: 1px solid rgba(0,0,0,.22); border-top: 0; box-shadow: 0 0 0px 4px rgba(0,0,0,.04)}*/ +body.collapsed #container{margin: auto; width: 980px; border: 1px solid rgba(0,0,0,.22); border-top: 0; box-shadow: 0 0 0px 4px rgba(0,0,0,.04)} diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6d0edace..070def96 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,7 @@ class ApplicationController < ActionController::Base before_filter :authenticate_user! + before_filter :view_style + protect_from_forgery helper_method :abilities, :can? @@ -73,4 +75,12 @@ class ApplicationController < ActionController::Base def require_non_empty_project redirect_to @project unless @project.repo_exists? end + + def view_style + if params[:view_style] == "collapsed" + cookies[:view_style] = "collapsed" + elsif params[:view_style] == "fluid" + cookies[:view_style] = "" + end + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 3aa40c99..70984804 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -4,6 +4,14 @@ module ApplicationHelper "http://www.gravatar.com/avatar/#{Digest::MD5.hexdigest(user_email)}?s=40&d=identicon" end + def body_class(default_class = nil) + main = content_for(:body_class).blank? ? + default_class : + content_for(:body_class) + + [main, cookies[:view_style]].join(" ") + end + def commit_name(project, commit) if project.commit.id == commit.id "master" diff --git a/app/views/layouts/_head_panel.html.erb b/app/views/layouts/_head_panel.html.erb index a64aa3b5..6db1d389 100644 --- a/app/views/layouts/_head_panel.html.erb +++ b/app/views/layouts/_head_panel.html.erb @@ -1,19 +1,29 @@
          -

          - GITLAB

          -
          - - <% if current_user %> <%= javascript_tag do %> $(function() { diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 8df7881c..e02dbe04 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -9,7 +9,7 @@ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)} + %body{ :class => body_class('project-page'), :id => yield(:boyd_id)} #container = render :partial => "layouts/flash" = render :partial => "layouts/head_panel" diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index eedbf116..030f1999 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -13,7 +13,7 @@ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body{ :class => yield(:body_class), :id => yield(:boyd_id)} + %body{ :class => body_class, :id => yield(:boyd_id)} #container = render :partial => "layouts/flash" = render :partial => "layouts/head_panel" diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index a33d9d5d..2fd30dcd 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -9,7 +9,7 @@ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)} + %body{ :class => body_class('project-page'), :id => yield(:boyd_id)} #container = render :partial => "layouts/flash" = render :partial => "layouts/head_panel" diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index f8d8221a..ee6581ec 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -9,7 +9,7 @@ = javascript_tag do REQ_URI = "#{request.env["REQUEST_URI"]}"; REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body{ :class => content_for?(:body_class) ? yield(:body_class) : 'project-page', :id => yield(:boyd_id)} + %body{ :class => body_class('project-page'), :id => yield(:boyd_id)} #container = render :partial => "layouts/flash" = render :partial => "layouts/head_panel" From 5d526717d626c072b6eb522e132cc30d9d96d60b Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Fri, 4 Nov 2011 01:16:12 +0200 Subject: [PATCH 159/176] increase max size of public to 1600 bytes --- app/models/key.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/key.rb b/app/models/key.rb index 1559b5bd..5fe30734 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -8,7 +8,7 @@ class Key < ActiveRecord::Base validates :key, :presence => true, :uniqueness => true, - :length => { :within => 0..1024 } + :length => { :within => 0..1600 } before_save :set_identifier after_save :update_gitosis From 6977150f04be1bfe365e1cd86e3f8143c34a51bf Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Fri, 4 Nov 2011 09:42:36 +0200 Subject: [PATCH 160/176] integrate tags plugins --- Gemfile | 2 + Gemfile.lock | 3 + app/models/project.rb | 2 + ...101222453_acts_as_taggable_on_migration.rb | 28 ++++ vendor/assets/javascripts/jquery.tagify.js | 143 ++++++++++++++++++ .../stylesheets/jquery-ui/jquery.tagify.css | 34 +++++ 6 files changed, 212 insertions(+) create mode 100644 db/migrate/20111101222453_acts_as_taggable_on_migration.rb create mode 100644 vendor/assets/javascripts/jquery.tagify.js create mode 100644 vendor/assets/stylesheets/jquery-ui/jquery.tagify.css diff --git a/Gemfile b/Gemfile index 8da55b10..f32c13f0 100644 --- a/Gemfile +++ b/Gemfile @@ -21,6 +21,8 @@ gem "git" gem "acts_as_list" gem 'rdiscount' +gem 'acts-as-taggable-on', '~>2.1.0' + group :assets do gem 'sass-rails', " ~> 3.1.0" gem 'coffee-rails', "~> 3.1.0" diff --git a/Gemfile.lock b/Gemfile.lock index f66e832e..e557ee43 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,6 +54,8 @@ GEM activesupport (= 3.1.0) activesupport (3.1.0) multi_json (~> 1.0) + acts-as-taggable-on (2.1.1) + rails acts_as_list (0.1.4) addressable (2.2.6) ansi (1.3.0) @@ -246,6 +248,7 @@ PLATFORMS ruby DEPENDENCIES + acts-as-taggable-on (~> 2.1.0) acts_as_list annotate! autotest diff --git a/app/models/project.rb b/app/models/project.rb index befa1c6b..de68f451 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -9,6 +9,8 @@ class Project < ActiveRecord::Base has_many :notes, :dependent => :destroy has_many :snippets, :dependent => :destroy + acts_as_taggable + validates :name, :uniqueness => true, :presence => true, diff --git a/db/migrate/20111101222453_acts_as_taggable_on_migration.rb b/db/migrate/20111101222453_acts_as_taggable_on_migration.rb new file mode 100644 index 00000000..16610615 --- /dev/null +++ b/db/migrate/20111101222453_acts_as_taggable_on_migration.rb @@ -0,0 +1,28 @@ +class ActsAsTaggableOnMigration < ActiveRecord::Migration + def self.up + create_table :tags do |t| + t.string :name + end + + create_table :taggings do |t| + t.references :tag + + # You should make sure that the column created is + # long enough to store the required class names. + t.references :taggable, :polymorphic => true + t.references :tagger, :polymorphic => true + + t.string :context + + t.datetime :created_at + end + + add_index :taggings, :tag_id + add_index :taggings, [:taggable_id, :taggable_type, :context] + end + + def self.down + drop_table :taggings + drop_table :tags + end +end diff --git a/vendor/assets/javascripts/jquery.tagify.js b/vendor/assets/javascripts/jquery.tagify.js new file mode 100644 index 00000000..f22d4c71 --- /dev/null +++ b/vendor/assets/javascripts/jquery.tagify.js @@ -0,0 +1,143 @@ +/* Author: Alicia Liu */ + +(function ($) { + + $.widget("ui.tagify", { + options: { + delimiters: [13, 188], // what user can type to complete a tag in char codes: [enter], [comma] + outputDelimiter: ',', // delimiter for tags in original input field + cssClass: 'tagify-container', // CSS class to style the tagify div and tags, see stylesheet + addTagPrompt: 'add tags' // placeholder text + }, + + _create: function() { + var self = this, + el = self.element, + opts = self.options; + + this.tags = []; + + // hide text field and replace with a div that contains it's own input field for entering tags + this.tagInput = $("") + .attr( 'placeholder', opts.addTagPrompt ) + .keypress( function(e) { + var $this = $(this), + pressed = e.which; + + for ( i in opts.delimiters ) { + + if (pressed == opts.delimiters[i]) { + self.add( $this.val() ); + e.preventDefault(); + return false; + } + } + }) + // for some reason, in Safari, backspace is only recognized on keyup + .keyup( function(e) { + var $this = $(this), + pressed = e.which; + + // if backspace is hit with no input, remove the last tag + if (pressed == 8) { // backspace + if ( $this.val() == "" ) { + self.remove(); + return false; + } + return; + } + }); + + this.tagDiv = $("
          ") + .addClass( opts.cssClass ) + .click( function() { + $(this).children('input').focus(); + }) + .append( this.tagInput ) + .insertAfter( el.hide() ); + + // if the field isn't empty, parse the field for tags, and prepopulate existing tags + var initVal = $.trim( el.val() ); + + if ( initVal ) { + var initTags = initVal.split( opts.outputDelimiter ); + $.each( initTags, function(i, tag) { + self.add( tag ); + }); + } + }, + + _setOption: function( key, value ) { + options.key = value; + }, + + // add a tag, public function + add: function(text) { + var self = this; + text = text || self.tagInput.val(); + if (text) { + var tagIndex = self.tags.length; + + var removeButton = $("x") + .click( function() { + self.remove( tagIndex ); + return false; + }); + var newTag = $("") + .text( text ) + .append( removeButton ); + + self.tagInput.before( newTag ); + self.tags.push( text ); + self.tagInput.val(''); + } + }, + + // remove a tag by index, public function + // if index is blank, remove the last tag + remove: function( tagIndex ) { + var self = this; + if ( tagIndex == null || tagIndex === (self.tags.length - 1) ) { + this.tagDiv.children("span").last().remove(); + self.tags.pop(); + } + if ( typeof(tagIndex) == 'number' ) { + // otherwise just hide this tag, and we don't mess up the index + this.tagDiv.children( "span:eq(" + tagIndex + ")" ).hide(); + // we rely on the serialize function to remove null values + delete( self.tags[tagIndex] ); + } + }, + + // serialize the tags with the given delimiter, and write it back into the tagified field + serialize: function() { + var self = this; + var delim = self.options.outputDelimiter; + var tagsStr = self.tags.join( delim ); + + // our tags might have deleted entries, remove them here + var dupes = new RegExp(delim + delim + '+', 'g'); // regex: /,,+/g + var ends = new RegExp('^' + delim + '|' + delim + '$', 'g'); // regex: /^,|,$/g + var outputStr = tagsStr.replace( dupes, delim ).replace(ends, ''); + + self.element.val(outputStr); + return outputStr; + }, + + inputField: function() { + return this.tagInput; + }, + + containerDiv: function() { + return this.tagDiv; + }, + + // remove the div, and show original input + destroy: function() { + $.Widget.prototype.destroy.apply(this); + this.tagDiv.remove(); + this.element.show(); + } + }); + +})(jQuery); \ No newline at end of file diff --git a/vendor/assets/stylesheets/jquery-ui/jquery.tagify.css b/vendor/assets/stylesheets/jquery-ui/jquery.tagify.css new file mode 100644 index 00000000..d6c178f7 --- /dev/null +++ b/vendor/assets/stylesheets/jquery-ui/jquery.tagify.css @@ -0,0 +1,34 @@ +/* Tagify styles +Author: Alicia Liu test +*/ + +.tagify-container { +} + +.tagify-container > span { + display: inline-block; + padding: 8px 11px 8px 11px; + margin: 1px 5px 0px 0px; + border-radius: 4px; + border: 1px solid #d0e1ff; + background-color: #d0e1ff; + color: #0f326d; + font-weight: bold; + font-size: 14px; +} + +.tagify-container > span > a { + padding-left: 5px !important; + color: #83a5e1; + text-decoration: none; + font-weight: bold; +} + +.tagify-container > input { + border: 0 none; + width: 100px !important; +} + +.tagify-container > input:focus { + outline: none; +} \ No newline at end of file From 687290a00d71540ae809ae9ef172771ce7c46778 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 4 Nov 2011 09:46:58 +0200 Subject: [PATCH 161/176] fixed brach switch --- app/views/commits/index.html.haml | 2 +- app/views/projects/_refs.html.haml | 2 +- app/views/projects/_tree.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/commits/index.html.haml b/app/views/commits/index.html.haml index 7999b94c..b9650145 100644 --- a/app/views/commits/index.html.haml +++ b/app/views/commits/index.html.haml @@ -12,7 +12,7 @@ \/ %a{:href => "#"}= params[:path].split("/").join(" / ") -.right= render "projects/refs" +.right= render :partial => "projects/refs", :locals => { :destination => project_commits_path(@project) } %div{:id => dom_id(@project)} = render "commits" diff --git a/app/views/projects/_refs.html.haml b/app/views/projects/_refs.html.haml index f7712d3d..60b17c7f 100644 --- a/app/views/projects/_refs.html.haml +++ b/app/views/projects/_refs.html.haml @@ -1,4 +1,4 @@ -= form_tag project_commits_path(@project), :method => :get, :class => "project-refs-form" do += form_tag destination, :method => :get, :class => "project-refs-form" do = select_tag "ref", grouped_options_refs, :onchange => "this.form.submit();", :class => "project-refs-select" diff --git a/app/views/projects/_tree.html.haml b/app/views/projects/_tree.html.haml index f70bbb7a..8fdf72f0 100644 --- a/app/views/projects/_tree.html.haml +++ b/app/views/projects/_tree.html.haml @@ -17,7 +17,7 @@ \/ = link_to truncate(part, :length => 40), tree_file_project_path(@project, :path => part_path, :commit_id => @commit.try(:id), :branch => @branch, :tag => @tag), :remote => :true   - .right= render "projects/refs" + .right= render :partial => "projects/refs", :locals => { :destination => tree_project_path(@project) } .clear #tree-content-holder From b946da44695c9c8fe8867bb87bcdf801c52177d3 Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Fri, 4 Nov 2011 10:11:14 +0200 Subject: [PATCH 162/176] added tags to form --- app/assets/javascripts/application.js | 1 + app/assets/stylesheets/application.css | 1 + app/views/projects/_form.html.haml | 17 +++++++++++++++++ db/schema.rb | 19 ++++++++++++++++++- 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 86887fdd..b1e95736 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -8,6 +8,7 @@ //= require jquery-ui //= require jquery_ujs //= require jquery.ui.selectmenu +//= require jquery.tagify //= require jquery.cookie //= require_tree . diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 777f3fc1..e170dc07 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -4,6 +4,7 @@ * the top of the compiled file, but it's generally better to create a new file per style scope. *= require jquery-ui/jquery-ui *= require jquery-ui/jquery.ui.selectmenu + *= require jquery-ui/jquery.tagify *= require_self *= require_tree . */ diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 164f1d45..605a2f45 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -25,6 +25,11 @@ .left= f.label :code %cite.right http://yourserver/ %td= f.text_field :code, :placeholder => "example" + + %tr + %td= f.label :tag_list + %td= f.text_area :tag_list, :placeholder => "project tags", :style => "height:50px", :id => :tag_field + .field = f.label :description %br/ @@ -41,8 +46,20 @@ %h3.prepend-top Creating project & repository. Please wait for few minutes - else %h3.prepend-top Updating project & repository. Please wait for few minutes + :javascript $('.new_project, .edit_project').bind('ajax:before', function() { $(this).find(".form_content").hide(); $('.ajax_loader').show(); }); + +:javascript + $(function(){ + var tag_field = $('#tag_field').tagify(); + + $('form').submit( function() { + var tag_field = $('#tag_field') + tag_field.val( tag_field.tagify('serialize') ); + return true; + }); + }) diff --git a/db/schema.rb b/db/schema.rb index 13c4db0c..3d430f4c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20111027152724) do +ActiveRecord::Schema.define(:version => 20111101222453) do create_table "issues", :force => true do |t| t.string "title" @@ -68,6 +68,23 @@ ActiveRecord::Schema.define(:version => 20111027152724) do t.datetime "expires_at" end + create_table "taggings", :force => true do |t| + t.integer "tag_id" + t.integer "taggable_id" + t.string "taggable_type" + t.integer "tagger_id" + t.string "tagger_type" + t.string "context" + t.datetime "created_at" + end + + add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" + add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context" + + create_table "tags", :force => true do |t| + t.string "name" + end + create_table "users", :force => true do |t| t.string "email", :default => "", :null => false t.string "encrypted_password", :limit => 128, :default => "", :null => false From ca1e3d05796484424057d071b726779537868384 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 4 Nov 2011 09:37:38 -0400 Subject: [PATCH 163/176] wall login in progress --- app/assets/images/ajax-loader.gif | Bin 6820 -> 4178 bytes app/assets/javascripts/application.js | 4 +- app/assets/javascripts/note.js | 65 +++++++++++++++++++++++ app/assets/stylesheets/projects.css.scss | 45 ++++------------ app/controllers/projects_controller.rb | 14 ++--- app/views/notes/_notes.html.haml | 4 +- app/views/notes/_show.html.haml | 20 ++++--- app/views/notes/create.js.haml | 1 - app/views/projects/wall.html.haml | 20 ++----- app/views/projects/wall.js.haml | 11 +++- 10 files changed, 110 insertions(+), 74 deletions(-) create mode 100644 app/assets/javascripts/note.js diff --git a/app/assets/images/ajax-loader.gif b/app/assets/images/ajax-loader.gif index 0ca7ada960568fff04400cda966fbdcb106abfa2..c97ec6ea9739a68e25637c0aa4adaaea05e3e4ca 100644 GIT binary patch literal 4178 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 diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 86887fdd..23845ea5 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -20,6 +20,6 @@ $(function(){ $('select#tag').selectmenu({style:'popup', width:200}); }); -function updatePage(){ - $.ajax({type: "GET", url: location.href, dataType: "script"}); +function updatePage(data){ + $.ajax({type: "GET", url: location.href, data: data, dataType: "script"}); } diff --git a/app/assets/javascripts/note.js b/app/assets/javascripts/note.js new file mode 100644 index 00000000..71279fc4 --- /dev/null +++ b/app/assets/javascripts/note.js @@ -0,0 +1,65 @@ +var NoteList = { + +first_id: 0, +last_id: 0, +resource_name: null, + +init: + function(resource_name, first_id, last_id) { + this.resource_name = resource_name; + this.first_id = first_id; + this.last_id = last_id; + this.initRefresh(); + this.initLoadMore(); + }, + +getOld: + function() { + $('.loading').show(); + $.ajax({ + type: "GET", + url: location.href, + data: "first_id=" + this.first_id, + complete: function(){ $('.loading').hide()}, + dataType: "script"}); + }, + +append: + function(id, html) { + this.first_id = id; + $("#notes-list").append(html); + this.initLoadMore(); + }, + +prepend: + function(id, html) { + this.last_id = id; + $("#notes-list").prepend(html); + }, + +getNew: + function() { + // refersh notes list + $.ajax({ + type: "GET", + url: location.href, + data: "last_id=" + this.last_id, + dataType: "script"}); + }, + +initRefresh: + function() { + // init timer + var int = setInterval("NoteList.getNew()", 20000); + }, + +initLoadMore: + function() { + $(window).bind('scroll', function(){ + if($(window).scrollTop() == $(document).height() - $(window).height()){ + $(window).unbind('scroll'); + NoteList.getOld(); + } + }); + } +} diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 4e4bcccc..06063b16 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -421,31 +421,6 @@ input.ssh_project_url { list-style:none; margin:0px; padding:0px; - - li { - display:list-item; - padding:8px; - margin:0px; - background: #F7FBFC; - border-top: 1px solid #E2EAEE; - - &:first-child { - border-top: none; - } - &:nth-child(2n+1) { - background: white; - } - p { - margin-bottom: 4px; - font-size: 13px; - color:#111; - } - } - cite { - &.ago { - color:#666; - } - } } .notes_count { @@ -460,14 +435,6 @@ input.ssh_project_url { right: 6px; top: 6px; } -.note_author { - float:left; - width:60px; -} -.note_content { - float:left; - width:650px; -} .issue_notes { .note_content { @@ -556,8 +523,7 @@ input.ssh_project_url { } .commit, -.message, -#notes-list{ +.message{ .author { background: #eaeaea; color: #333; @@ -719,3 +685,12 @@ table.highlighttable pre{ .project-refs-select { width:200px; } + + +body.project-page #notes-list .note {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} +body.project-page #notes-list .note {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} +body.project-page #notes-list .note img{float: left; margin-right: 10px;} +body.project-page #notes-list .note span.note-title{display: block;} +body.project-page #notes-list .note span.note-title{margin-bottom: 10px} +body.project-page #notes-list .note span.note-author{color: #999; font-weight: normal; font-style: italic;} +body.project-page #notes-list .note span.note-author strong{font-weight: bold; font-style: normal;} diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index e046add3..067245c4 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -86,13 +86,15 @@ class ProjectsController < ApplicationController def wall @note = Note.new @notes = @project.common_notes.order("created_at DESC") + @notes = @notes.fresh.limit(20) - @notes = case params[:view] - when "week" then @notes.since((Date.today - 7.days).at_beginning_of_day) - when "all" then @notes.all - when "day" then @notes.since(Date.today.at_beginning_of_day) - else @notes.fresh.limit(10) - end + respond_to do |format| + format.html + format.js do + @notes = @notes.where("id > ?", params[:last_id]) if params[:last_id] + @notes = @notes.where("id < ?", params[:first_id]) if params[:first_id] + end + end end # diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml index e7cc2360..e33050b0 100644 --- a/app/views/notes/_notes.html.haml +++ b/app/views/notes/_notes.html.haml @@ -20,8 +20,8 @@ $("#submit_note").removeAttr("disabled"); }) -- if ["issues", "projects"].include?(controller.controller_name) +-#- if ["issues", "projects"].include?(controller.controller_name) :javascript $(function(){ - var int =self.setInterval("updatePage()", 20000); + var int =self.setInterval("updatePage('ref=#{params[:ref]}')", 20000); }); diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_show.html.haml index 187d0a3c..164733a5 100644 --- a/app/views/notes/_show.html.haml +++ b/app/views/notes/_show.html.haml @@ -1,17 +1,15 @@ -%li{:id => dom_id(note)} - %div.note_author - = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" - %div.note_content.left +%li{:id => dom_id(note), :class => "note"} + = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" + %div.note-author + %strong= note.author_name + = time_ago_in_words(note.updated_at) + - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) + = link_to 'Remove', [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-note right negative" + + %div.note-title = markdown(note.note) - if note.attachment.url Attachment: = link_to note.attachment_identifier, note.attachment.url, :target => "_blank" - %br - %span.author= note.author.name - %cite.ago - = time_ago_in_words(note.updated_at) - ago %br - - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) - = link_to 'Remove', [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-note right negative" .clear diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index a04130e8..ffc80140 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -1,7 +1,6 @@ - if @note.valid? :plain $("#new_note .errors").remove(); - updatePage(); $('#note_note').val(""); - else :plain diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml index 63c9613a..2bc3150a 100644 --- a/app/views/projects/wall.html.haml +++ b/app/views/projects/wall.html.haml @@ -1,29 +1,19 @@ %div.wall_page - if can? current_user, :write_note, @project = render "notes/form" - .right - = form_tag wall_project_path(@project), :method => :get do - .span-2 - = radio_button_tag :view, "recent", (params[:view] || "recent") == "recent", :onclick => "this.form.submit()", :id => "recent_view" - = label_tag "recent_view","Recent" - .span-2 - = radio_button_tag :view, "day", params[:view] == "day", :onclick => "this.form.submit()", :id => "day_view" - = label_tag "day_view","Today" - .span-2 - = radio_button_tag :view, "week", params[:view] == "week", :onclick => "this.form.submit()", :id => "week_view" - = label_tag "week_view","Week" - .span-2 - = radio_button_tag :view, "all", params[:view] == "all", :onclick => "this.form.submit()", :id => "all_view" - = label_tag "all_view","All" .clear - %br %hr = render "notes/notes" +.loading{ :style => "display:none;"} + %center= image_tag "ajax-loader.gif" + :javascript $(function(){ $("#note_note").live("click", function(){ $(this).css("height", "100px"); $('.attach_holder').show(); }); + + NoteList.init("wall", #{@notes.last.id}, #{@notes.first.id}); }); diff --git a/app/views/projects/wall.js.haml b/app/views/projects/wall.js.haml index ae2ff32c..81417800 100644 --- a/app/views/projects/wall.js.haml +++ b/app/views/projects/wall.js.haml @@ -1,2 +1,9 @@ -:plain - $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); +- unless @notes.blank? + + - if params[:last_id] + :plain + NoteList.prepend(#{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); + + - if params[:first_id] + :plain + NoteList.append(#{@notes.last.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); From 8a23682fc5212918c931888bb7b468d167d19c33 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 4 Nov 2011 11:46:51 -0400 Subject: [PATCH 164/176] refactored too --- app/assets/stylesheets/projects.css.scss | 2 +- app/controllers/commits_controller.rb | 11 +++++++---- app/controllers/issues_controller.rb | 10 +++++++++- app/views/commits/show.js.haml | 9 +-------- app/views/issues/show.html.haml | 13 +++++++++++- app/views/issues/show.js.haml | 3 +-- app/views/notes/_load.js.haml | 10 ++++++++++ app/views/notes/_notes.html.haml | 25 ++++++++++++------------ app/views/notes/create.js.haml | 1 + app/views/projects/wall.html.haml | 15 +------------- app/views/projects/wall.js.haml | 10 +--------- 11 files changed, 56 insertions(+), 53 deletions(-) create mode 100644 app/views/notes/_load.js.haml diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 06063b16..ba18bfa0 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -540,7 +540,7 @@ input.ssh_project_url { font-size:14px; } -.wall_page { +#new_note { #note_note { height:25px; } diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index 79b97ed7..f6af56f8 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -28,12 +28,15 @@ class CommitsController < ApplicationController def show @commit = project.repo.commits(params[:id]).first - @notes = project.notes.where(:noteable_id => @commit.id, :noteable_type => "Commit") + @notes = project.notes.where(:noteable_id => @commit.id, :noteable_type => "Commit").order("created_at DESC").limit(20) @note = @project.notes.new(:noteable_id => @commit.id, :noteable_type => "Commit") - respond_to do |format| - format.html # show.html.erb - format.js + respond_to do |format| + format.html + format.js do + @notes = @notes.where("id > ?", params[:last_id]) if params[:last_id] + @notes = @notes.where("id < ?", params[:first_id]) if params[:first_id] + end end end end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 71c559a1..b6fd85b8 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -35,8 +35,16 @@ class IssuesController < ApplicationController end def show - @notes = @issue.notes.order("created_at ASC") + @notes = @issue.notes.order("created_at DESC").limit(20) @note = @project.notes.new(:noteable => @issue) + + respond_to do |format| + format.html + format.js do + @notes = @notes.where("id > ?", params[:last_id]) if params[:last_id] + @notes = @notes.where("id < ?", params[:first_id]) if params[:first_id] + end + end end def create diff --git a/app/views/commits/show.js.haml b/app/views/commits/show.js.haml index 9831bb29..ee31c0b8 100644 --- a/app/views/commits/show.js.haml +++ b/app/views/commits/show.js.haml @@ -1,8 +1 @@ --#:plain - $("#side-commit-preview").remove(); - var side = $("
          "); - side.html("#{escape_javascript(render "commits/show")}"); - $("##{dom_id(@project)}").parent().append(side); - $("##{dom_id(@project)}").addClass("span-14"); -:plain - $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); += render "notes/load" diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 371a8033..669784ba 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -1,8 +1,10 @@ %h2 = "Issue ##{@issue.id} - #{html_escape(@issue.title)}" .left.width-65p - -#= simple_format html_escape(@issue.content) .issue_notes= render "notes/notes" + + .loading{ :style => "display:none;"} + %center= image_tag "ajax-loader.gif" .right.width-30p .span-8 - if @issue.closed @@ -55,3 +57,12 @@ .right= link_to 'Destroy', [@project, @issue], :confirm => 'Are you sure?', :method => :delete, :class => "lbutton delete-issue negative", :id => "destroy_issue_#{@issue.id}" .clear +:javascript + $(function(){ + $("#note_note").live("click", function(){ + $(this).css("height", "100px"); + $('.attach_holder').show(); + }); + + NoteList.init("wall", #{@notes.last.id}, #{@notes.first.id}); + }); diff --git a/app/views/issues/show.js.haml b/app/views/issues/show.js.haml index ae2ff32c..ee31c0b8 100644 --- a/app/views/issues/show.js.haml +++ b/app/views/issues/show.js.haml @@ -1,2 +1 @@ -:plain - $("#notes-list").html("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); += render "notes/load" diff --git a/app/views/notes/_load.js.haml b/app/views/notes/_load.js.haml new file mode 100644 index 00000000..f560f0bd --- /dev/null +++ b/app/views/notes/_load.js.haml @@ -0,0 +1,10 @@ +- unless @notes.blank? + + - if params[:last_id] + :plain + NoteList.prepend(#{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); + + - if params[:first_id] + :plain + NoteList.append(#{@notes.last.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); + diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml index e33050b0..4a5c3aab 100644 --- a/app/views/notes/_notes.html.haml +++ b/app/views/notes/_notes.html.haml @@ -1,12 +1,8 @@ -- if controller.action_name == "wall" - %ul#notes-list= render "notes/notes_list" - -- else - %ul#notes-list= render "notes/notes_list" - %br - %br - - if can? current_user, :write_note, @project - = render "notes/form" +- if can? current_user, :write_note, @project + = render "notes/form" +.clear +%hr +%ul#notes-list= render "notes/notes_list" :javascript $('.delete-note').live('ajax:success', function() { @@ -20,8 +16,11 @@ $("#submit_note").removeAttr("disabled"); }) --#- if ["issues", "projects"].include?(controller.controller_name) - :javascript - $(function(){ - var int =self.setInterval("updatePage('ref=#{params[:ref]}')", 20000); + $(function(){ + $("#note_note").live("click", function(){ + $(this).css("height", "100px"); + $('.attach_holder').show(); }); + + NoteList.init("wall", #{@notes.last.try(:id) || 0}, #{@notes.first.try(:id) || 0}); + }); diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index ffc80140..cf804493 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -2,6 +2,7 @@ :plain $("#new_note .errors").remove(); $('#note_note').val(""); + NoteList.prepend(#{@note.id}, "#{escape_javascript(render :partial => "notes/show", :locals => {:note => @note})}"); - else :plain $("#new_note").replaceWith("#{escape_javascript(render('form'))}"); diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml index 2bc3150a..4f0ec41e 100644 --- a/app/views/projects/wall.html.haml +++ b/app/views/projects/wall.html.haml @@ -1,19 +1,6 @@ %div.wall_page - - if can? current_user, :write_note, @project - = render "notes/form" - .clear - %hr -= render "notes/notes" + = render "notes/notes" .loading{ :style => "display:none;"} %center= image_tag "ajax-loader.gif" -:javascript - $(function(){ - $("#note_note").live("click", function(){ - $(this).css("height", "100px"); - $('.attach_holder').show(); - }); - - NoteList.init("wall", #{@notes.last.id}, #{@notes.first.id}); - }); diff --git a/app/views/projects/wall.js.haml b/app/views/projects/wall.js.haml index 81417800..ee31c0b8 100644 --- a/app/views/projects/wall.js.haml +++ b/app/views/projects/wall.js.haml @@ -1,9 +1 @@ -- unless @notes.blank? - - - if params[:last_id] - :plain - NoteList.prepend(#{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); - - - if params[:first_id] - :plain - NoteList.append(#{@notes.last.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); += render "notes/load" From 2ed5211dad88dc0b0cccb1104ed2180192609950 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 4 Nov 2011 11:59:00 -0400 Subject: [PATCH 165/176] fixes --- app/views/issues/show.html.haml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 669784ba..7321f635 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -56,13 +56,3 @@ = link_to 'Edit', edit_project_issue_path(@project, @issue), :class => "lbutton positive", :remote => true .right= link_to 'Destroy', [@project, @issue], :confirm => 'Are you sure?', :method => :delete, :class => "lbutton delete-issue negative", :id => "destroy_issue_#{@issue.id}" .clear - -:javascript - $(function(){ - $("#note_note").live("click", function(){ - $(this).css("height", "100px"); - $('.attach_holder').show(); - }); - - NoteList.init("wall", #{@notes.last.id}, #{@notes.first.id}); - }); From 0b0e0225adfc83ed951118b3c3e82167add9fd03 Mon Sep 17 00:00:00 2001 From: gitlabhq Date: Fri, 4 Nov 2011 12:20:52 -0400 Subject: [PATCH 166/176] css fixes --- app/assets/stylesheets/projects.css.scss | 1 - app/views/issues/show.html.haml | 4 ---- app/views/notes/_show.html.haml | 4 +++- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index ba18bfa0..766138ee 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -686,7 +686,6 @@ table.highlighttable pre{ width:200px; } - body.project-page #notes-list .note {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} body.project-page #notes-list .note {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} body.project-page #notes-list .note img{float: left; margin-right: 10px;} diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 7321f635..8267a850 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -7,10 +7,6 @@ %center= image_tag "ajax-loader.gif" .right.width-30p .span-8 - - if @issue.closed - %center.success Closed - - else - %center.error Open %table.round-borders %tr %td Title: diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_show.html.haml index 164733a5..5d766291 100644 --- a/app/views/notes/_show.html.haml +++ b/app/views/notes/_show.html.haml @@ -2,7 +2,9 @@ = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" %div.note-author %strong= note.author_name - = time_ago_in_words(note.updated_at) + %cite + = time_ago_in_words(note.updated_at) + ago - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) = link_to 'Remove', [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-note right negative" From 586c53ea0594a327b346c6fed38528a1f508c9e1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 5 Nov 2011 13:59:43 +0200 Subject: [PATCH 167/176] fixed notes loading/paging --- app/assets/javascripts/note.js | 24 ++++++++++++++++++++++- app/controllers/application_controller.rb | 12 ++++++++++++ app/controllers/commits_controller.rb | 5 +---- app/controllers/issues_controller.rb | 5 +---- app/controllers/projects_controller.rb | 5 +---- app/views/notes/_load.js.haml | 11 +++++++++-- 6 files changed, 47 insertions(+), 15 deletions(-) diff --git a/app/assets/javascripts/note.js b/app/assets/javascripts/note.js index 71279fc4..7acc81e5 100644 --- a/app/assets/javascripts/note.js +++ b/app/assets/javascripts/note.js @@ -31,6 +31,15 @@ append: this.initLoadMore(); }, +replace: + function(fid, lid, html) { + this.first_id = fid; + this.last_id = lid; + $("#notes-list").html(html); + this.initLoadMore(); + }, + + prepend: function(id, html) { this.last_id = id; @@ -47,10 +56,23 @@ getNew: dataType: "script"}); }, +refresh: + function() { + // refersh notes list + $.ajax({ + type: "GET", + url: location.href, + data: "first_id=" + this.first_id + "&last_id=" + this.last_id, + dataType: "script"}); + }, + + + initRefresh: function() { // init timer - var int = setInterval("NoteList.getNew()", 20000); + var intNew = setInterval("NoteList.getNew()", 15000); + var intRefresh = setInterval("NoteList.refresh()", 90000); }, initLoadMore: diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 070def96..5c25d7d6 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -83,4 +83,16 @@ class ApplicationController < ActionController::Base cookies[:view_style] = "" end end + + def respond_with_notes + if params[:last_id] && params[:first_id] + @notes = @notes.where("id >= ?", params[:first_id]) + elsif params[:last_id] + @notes = @notes.where("id > ?", params[:last_id]) + elsif params[:first_id] + @notes = @notes.where("id < ?", params[:first_id]) + else + nil + end + end end diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index f6af56f8..fa0d0b57 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -33,10 +33,7 @@ class CommitsController < ApplicationController respond_to do |format| format.html - format.js do - @notes = @notes.where("id > ?", params[:last_id]) if params[:last_id] - @notes = @notes.where("id < ?", params[:first_id]) if params[:first_id] - end + format.js { respond_with_notes } end end end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index b6fd85b8..7ff1ccb3 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -40,10 +40,7 @@ class IssuesController < ApplicationController respond_to do |format| format.html - format.js do - @notes = @notes.where("id > ?", params[:last_id]) if params[:last_id] - @notes = @notes.where("id < ?", params[:first_id]) if params[:first_id] - end + format.js { respond_with_notes } end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 067245c4..ef7eb921 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -90,10 +90,7 @@ class ProjectsController < ApplicationController respond_to do |format| format.html - format.js do - @notes = @notes.where("id > ?", params[:last_id]) if params[:last_id] - @notes = @notes.where("id < ?", params[:first_id]) if params[:first_id] - end + format.js { respond_with_notes } end end diff --git a/app/views/notes/_load.js.haml b/app/views/notes/_load.js.haml index f560f0bd..c7ec9ed3 100644 --- a/app/views/notes/_load.js.haml +++ b/app/views/notes/_load.js.haml @@ -1,10 +1,17 @@ - unless @notes.blank? - - if params[:last_id] + - if params[:last_id] && params[:first_id] + :plain + NoteList.replace(#{@notes.last.id}, #{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); + + + - elsif params[:last_id] :plain NoteList.prepend(#{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); - - if params[:first_id] + - elsif params[:first_id] :plain NoteList.append(#{@notes.last.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); + - else + :plain From 5eecbfdb10f97a216b585e7bddcbbd68f71f6ccc Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 5 Nov 2011 14:26:06 +0200 Subject: [PATCH 168/176] commit paging fixes --- app/assets/javascripts/commits.js | 48 +++++++++++++++++++++++++ app/controllers/commits_controller.rb | 5 +-- app/views/commits/_commits.html.haml | 1 - app/views/commits/index.html.haml | 12 ++++++- app/views/commits/index.js.erb | 2 -- app/views/commits/index.js.haml | 3 ++ app/views/layouts/application.html.haml | 11 ++---- 7 files changed, 68 insertions(+), 14 deletions(-) delete mode 100644 app/views/commits/index.js.erb create mode 100644 app/views/commits/index.js.haml diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js index a62e9330..bef7ed74 100644 --- a/app/assets/javascripts/commits.js +++ b/app/assets/javascripts/commits.js @@ -7,3 +7,51 @@ $(document).ready(function(){ } }); }); + + + +var CommitsList = { + +ref:null, +limit:0, +offset:0, + +init: + function(ref, limit) { + this.ref=ref; + this.limit=limit; + this.offset=limit; + this.initLoadMore(); + $('.loading').show(); + }, + +getOld: + function() { + $('.loading').show(); + $.ajax({ + type: "GET", + url: location.href, + data: "limit=" + this.limit + "&offset=" + this.offset + "&ref=" + this.ref, + complete: function(){ $('.loading').hide()}, + dataType: "script"}); + }, + +append: + function(count, html) { + $("#commits_list").append(html); + if(count > 0) { + this.offset += count; + this.initLoadMore(); + } + }, + +initLoadMore: + function() { + $(window).bind('scroll', function(){ + if($(window).scrollTop() == $(document).height() - $(window).height()){ + $(window).unbind('scroll'); + CommitsList.getOld(); + } + }); + } +} diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index fa0d0b57..79703cf1 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -13,11 +13,12 @@ class CommitsController < ApplicationController load_refs # load @branch, @tag & @ref @repo = project.repo + limit, offset = (params[:limit] || 20), (params[:offset] || 0) if params[:path] - @commits = @repo.log(@ref, params[:path], :max_count => params[:limit] || 100, :skip => params[:offset] || 0) + @commits = @repo.log(@ref, params[:path], :max_count => limit, :skip => offset) else - @commits = @repo.commits(@ref, params[:limit] || 100, params[:offset] || 0) + @commits = @repo.commits(@ref, limit, offset) end respond_to do |format| diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index 9761c65f..2d393993 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -22,4 +22,3 @@ %strong= commit.author_name = time_ago_in_words(commit.committed_date) ago -= more_commits_link if @commits.size > 99 diff --git a/app/views/commits/index.html.haml b/app/views/commits/index.html.haml index b9650145..0dfb2cff 100644 --- a/app/views/commits/index.html.haml +++ b/app/views/commits/index.html.haml @@ -15,4 +15,14 @@ .right= render :partial => "projects/refs", :locals => { :destination => project_commits_path(@project) } %div{:id => dom_id(@project)} - = render "commits" + #commits_list= render "commits" +.clear +.loading{ :style => "display:none;"} + %center= image_tag "ajax-loader.gif" + + + +:javascript + $(function(){ + CommitsList.init("#{@ref}", 20); + }); diff --git a/app/views/commits/index.js.erb b/app/views/commits/index.js.erb deleted file mode 100644 index 94daa396..00000000 --- a/app/views/commits/index.js.erb +++ /dev/null @@ -1,2 +0,0 @@ -$("#more-commits-link").remove(); -$('#<%= dom_id(@project)%>').append('<%= escape_javascript(render("commits")) %>'); diff --git a/app/views/commits/index.js.haml b/app/views/commits/index.js.haml new file mode 100644 index 00000000..39b7108c --- /dev/null +++ b/app/views/commits/index.js.haml @@ -0,0 +1,3 @@ +:plain + CommitsList.append(#{@commits.count}, "#{escape_javascript(render(:partial => 'commits/commits'))}"); + diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 030f1999..9022ecb1 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -2,11 +2,7 @@ %html %head %title - GitLab #{" - #{@project.name}" if @project && !@project.new_record?} - -#= stylesheet_link_tag 'blueprint/screen', :media => "screen, projection" - -#= stylesheet_link_tag 'blueprint/print', :media => "print" - -#= stylesheet_link_tag 'blueprint/plugins/buttons/screen', :media => "screen, projection" - -#= stylesheet_link_tag 'blueprint/plugins/link-icons/screen', :media => "screen, projection" + GitLab = stylesheet_link_tag "application" = javascript_include_tag "application" = csrf_meta_tags @@ -17,6 +13,5 @@ #container = render :partial => "layouts/flash" = render :partial => "layouts/head_panel" - %div{ :id => "main", :role => "main", :class => "container_4" } - = render :partial => "layouts/page_title" - = yield + = render :partial => "layouts/page_title" + = yield From 31a9d6531dcbfc72babf3da52d17cde61b4bcc04 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 5 Nov 2011 14:45:52 +0200 Subject: [PATCH 169/176] commits notes under diff. tab removed --- app/assets/stylesheets/projects.css.scss | 7 ++++--- app/views/commits/show.html.haml | 24 +++++------------------- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 766138ee..0e1ad931 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -52,7 +52,8 @@ background: #eee; } .diff_file_content { - overflow-x: scroll; + overflow:auto; + overflow-y:hidden; background:#fff; color:#333; font-size: 12px; @@ -174,9 +175,9 @@ a { .old_line, .new_line { background:#ECECEC; color:#777; - width:15px; + width:30px; float:left; - padding: 0px 10px; + padding: 0px 5px; border-right: 1px solid #ccc; } } diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml index 3bd9145e..b42b23de 100644 --- a/app/views/commits/show.html.haml +++ b/app/views/commits/show.html.haml @@ -1,5 +1,5 @@ %h3 - = "[ #{@commit.committer} ] #{truncate(@commit.safe_message)}" + = "[ #{@commit.author_name} ] #{truncate(@commit.safe_message, :length => 70)}" -#= link_to 'Back', project_commits_path(@project), :class => "button" %table.round-borders %tr @@ -8,12 +8,9 @@ %tr %td Author %td= @commit.author_name - %tr - %td Commiter - %td= @commit.committer %tr %td Commited Date - %td= @commit.committed_date + %td= @commit.committed_date.stamp("21 Aug 2011, 11:15pm") %tr %td Message %td @@ -24,18 +21,7 @@ %td= link_to 'Browse Code', tree_project_path(@project, :commit_id => @commit.id) .clear -#tabs - %ul - %li - %a{ :href => "#tabs-1" } Diff - %li - %a{ :href => "#tabs-2" } Comments - %span{ :class => "notes_count" }= @notes.count - %hr - #tabs-1 - = render "commits/diff" - #tabs-2 - = render "notes/notes" +%br -:javascript - $(function() { $( "#tabs" ).tabs(); }); += render "commits/diff" += render "notes/notes" From 1e5aa0effffa60cc5f5a953011cfb40a37b6a862 Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Sat, 5 Nov 2011 14:57:40 +0200 Subject: [PATCH 170/176] add tags autocomplete --- app/controllers/tags_controller.rb | 15 +++++++++++++ app/views/projects/_form.html.haml | 10 +++++++++ app/views/tags/autocomplete.html.haml | 2 ++ app/views/tags/index.html.haml | 2 ++ config/routes.rb | 3 +++ spec/requests/tags_spec.rb | 31 +++++++++++++++++++++++++++ 6 files changed, 63 insertions(+) create mode 100644 app/controllers/tags_controller.rb create mode 100644 app/views/tags/autocomplete.html.haml create mode 100644 app/views/tags/index.html.haml create mode 100644 spec/requests/tags_spec.rb diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb new file mode 100644 index 00000000..6ec3226a --- /dev/null +++ b/app/controllers/tags_controller.rb @@ -0,0 +1,15 @@ +class TagsController < ApplicationController + def index + end + + def autocomplete + tags = Project.tag_counts.limit 8 + tags = tags.where('name like ?', "%#{params[:term]}%") unless params[:term].blank? + tags = tags.map {|t| t.name} + + respond_to do |format| + format.json { render json: tags} + end + end + +end diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 605a2f45..059ee40c 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -57,9 +57,19 @@ $(function(){ var tag_field = $('#tag_field').tagify(); + + tag_field.tagify('inputField').autocomplete({ + source: '/tags/autocomplete.json', + position: { of: tag_field.tagify('containerDiv') }, + close: function(event, ui) { tag_field.tagify('add'); }, + }); + + $('form').submit( function() { var tag_field = $('#tag_field') tag_field.val( tag_field.tagify('serialize') ); return true; }); + + }) diff --git a/app/views/tags/autocomplete.html.haml b/app/views/tags/autocomplete.html.haml new file mode 100644 index 00000000..e5c86e7e --- /dev/null +++ b/app/views/tags/autocomplete.html.haml @@ -0,0 +1,2 @@ +%h1 Tags#autocomplete +%p Find me in app/views/tags/autocomplete.html.haml \ No newline at end of file diff --git a/app/views/tags/index.html.haml b/app/views/tags/index.html.haml new file mode 100644 index 00000000..7bf17b5e --- /dev/null +++ b/app/views/tags/index.html.haml @@ -0,0 +1,2 @@ +%h1 Tags#index +%p Find me in app/views/tags/index.html.haml \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index d45c32bd..c6b2d8b1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,7 @@ Gitlab::Application.routes.draw do + get "tags/index" + get "tags/autocomplete" + namespace :admin do resources :users resources :projects diff --git a/spec/requests/tags_spec.rb b/spec/requests/tags_spec.rb new file mode 100644 index 00000000..43d7a0ff --- /dev/null +++ b/spec/requests/tags_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe "Tags" do + before { login_as :user } + + # describe "GET 'tags/index'" do + # it "should be successful" do + # get 'tags/index' + # response.should be_success + # end + # end + + + describe "GET '/tags/autocomplete'" do + before do + @project = Factory :project + @project.add_access(@user, :read) + @project.tag_list = 'demo1' + @project.save + visit '/tags/autocomplete.json' + end + + + it "should contains tags" do + page.should have_content('demo1') + end +end + + + +end From 0499759204449a78ead1950c06fbab4dacfa84f2 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sat, 5 Nov 2011 15:31:54 +0200 Subject: [PATCH 171/176] issues & fixed layout --- app/assets/stylesheets/projects.css.scss | 42 +++++------------------ app/controllers/application_controller.rb | 6 ++++ app/views/issues/_show.html.haml | 14 ++++---- app/views/issues/index.html.haml | 10 +++--- app/views/issues/show.html.haml | 23 ++++++------- spec/requests/commits_notes_spec.rb | 1 - 6 files changed, 38 insertions(+), 58 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 0e1ad931..c4b5de8a 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -163,10 +163,6 @@ table.round-borders { padding:20px; } -//body { - //background: #eaeaea; -//} - a { color: #111; } @@ -232,43 +228,15 @@ input.ssh_project_url { text-align:center; } -.day-commits-table li.commit { - cursor:pointer; - - &:hover { - @include hover-color; - } -} - -/* -#FFF6BF -#FFD324 -*/ -#tree-slider tr.tree-item { - cursor:pointer; - - &:hover { - @include hover-color; - td { - @include hover-color; - } - } -} #projects-list .project { height:50px; } +#tree-slider .tree-item, #projects-list .project, #snippets-table .snippet, #issues-table .issue{ cursor:pointer; - - &:hover { - @include hover-color; - td { - @include hover-color; - } - } } .clear { @@ -563,6 +531,7 @@ input.ssh_project_url { @include round-borders-all(4px); padding:2px 4px; border:none; + text-shadow:none; &.high { background: #D12F19; @@ -687,6 +656,13 @@ table.highlighttable pre{ width:200px; } +.issues_filter { + margin-top:10px; + .left { + margin-right:15px; + } +} + body.project-page #notes-list .note {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} body.project-page #notes-list .note {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} body.project-page #notes-list .note img{float: left; margin-right: 10px;} diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 5c25d7d6..782612c0 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -82,6 +82,12 @@ class ApplicationController < ActionController::Base elsif params[:view_style] == "fluid" cookies[:view_style] = "" end + + @view_mode = if cookies[:view_style] == "collapsed" + :fixed + else + :fluid + end end def respond_with_notes diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml index 94cc03d1..05208d09 100644 --- a/app/views/issues/_show.html.haml +++ b/app/views/issues/_show.html.haml @@ -4,10 +4,11 @@ = image_tag "move.png" , :class => [:handle, :left] %td = image_tag gravatar_icon(issue.assignee.email), :class => "left", :width => 40, :style => "padding:0 5px;" - = truncate issue.assignee.name, :lenght => 20 + = issue.assignee.name %td ##{issue.id} %td - = truncate(html_escape(issue.title), :length => 60) + = truncate(html_escape(issue.title), :length => 200) + %br %br - if issue.critical %span.tag.high critical @@ -27,7 +28,8 @@ - else = check_box_tag "closed", 1, issue.closed, :disabled => true %td - - if can?(current_user, :admin_issue, @project) || issue.author == current_user - = link_to 'Edit', edit_project_issue_path(@project, issue), :class => "lbutton positive", :remote => true - - if can?(current_user, :admin_issue, @project) || issue.author == current_user - = link_to 'Destroy', [@project, issue], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-issue negative", :id => "destroy_issue_#{issue.id}" + - if @view_mode == :fluid + - if can?(current_user, :admin_issue, @project) || issue.author == current_user + = link_to 'Edit', edit_project_issue_path(@project, issue), :class => "lbutton positive", :remote => true + - if can?(current_user, :admin_issue, @project) || issue.author == current_user + = link_to 'Destroy', [@project, issue], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-issue negative", :id => "destroy_issue_#{issue.id}" diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml index a70c65d4..21e455b9 100644 --- a/app/views/issues/index.html.haml +++ b/app/views/issues/index.html.haml @@ -7,18 +7,18 @@ = hidden_field_tag :project_id, @project.id, { :id => 'project_id' } = search_field_tag :issue_search, nil, { :placeholder => 'Search', :class => 'issue_search' } - .right + .right.issues_filter = form_tag project_issues_path(@project), :method => :get do - .span-2 + .left = radio_button_tag :f, 0, (params[:f] || "0") == "0", :onclick => "this.form.submit()", :id => "open_issues", :class => "status" = label_tag "open_issues","Open" - .span-2 + .left = radio_button_tag :f, 2, params[:f] == "2", :onclick => "this.form.submit()", :id => "closed_issues", :class => "status" = label_tag "closed_issues","Closed" - .span-2 + .left = radio_button_tag :f, 3, params[:f] == "3", :onclick => "this.form.submit()", :id => "my_issues", :class => "status" = label_tag "my_issues","To Me" - .span-2 + .left = radio_button_tag :f, 1, params[:f] == "1", :onclick => "this.form.submit()", :id => "all_issues", :class => "status" = label_tag "all_issues","All" diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 8267a850..dc4ab338 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -1,5 +1,9 @@ %h2 - = "Issue ##{@issue.id} - #{html_escape(@issue.title)}" + %strong + Issue + = "##{@issue.id}" + – + = html_escape(@issue.title) .left.width-65p .issue_notes= render "notes/notes" @@ -8,14 +12,6 @@ .right.width-30p .span-8 %table.round-borders - %tr - %td Title: - %td - = truncate html_escape(@issue.title) - %tr - %td Project - %td - %strong= @issue.project.name %tr %td Author: %td @@ -39,7 +35,7 @@ %tr %td Closed? %td - - if can? current_user, :write_issue, @project + - if can? current_user, :write_issue, @issue = form_for([@project, @issue]) do |f| = f.check_box :closed, :onclick => "$(this).parent().submit();" = hidden_field_tag :status_only, true @@ -47,8 +43,9 @@ = check_box_tag "closed", 1, @issue.closed, :disabled => true - - if can?(current_user, :admin_issue, @issue) + - if can?(current_user, :write_issue, @issue) .clear - = link_to 'Edit', edit_project_issue_path(@project, @issue), :class => "lbutton positive", :remote => true - .right= link_to 'Destroy', [@project, @issue], :confirm => 'Are you sure?', :method => :delete, :class => "lbutton delete-issue negative", :id => "destroy_issue_#{@issue.id}" + %br + = link_to 'Edit', edit_project_issue_path(@project, @issue), :class => "lbutton positive", :remote => true + .right= link_to 'Destroy', [@project, @issue], :confirm => 'Are you sure?', :method => :delete, :class => "lbutton delete-issue negative", :id => "destroy_issue_#{@issue.id}" .clear diff --git a/spec/requests/commits_notes_spec.rb b/spec/requests/commits_notes_spec.rb index c424f4fc..69a492e9 100644 --- a/spec/requests/commits_notes_spec.rb +++ b/spec/requests/commits_notes_spec.rb @@ -12,7 +12,6 @@ describe "Issues" do describe "add new note", :js => true do before do visit project_commit_path(project, commit) - click_link "Comments" # notes tab fill_in "note_note", :with => "I commented this commit" click_button "Add note" end From 6e08b5cc857b3b218df0b20745ad295e79abc722 Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Sat, 5 Nov 2011 21:00:05 +0200 Subject: [PATCH 172/176] create tags page and made tag filter for projects --- app/assets/stylesheets/projects.css.scss | 14 ++++++++++++++ app/assets/stylesheets/tags.css.css | 16 ++++++++++++++++ app/controllers/projects_controller.rb | 4 +++- app/controllers/tags_controller.rb | 12 ++++-------- app/views/projects/_form.html.haml | 7 +------ app/views/projects/_list.html.haml | 7 ++++++- app/views/tags/autocomplete.html.haml | 2 -- app/views/tags/index.html.haml | 13 +++++++++++-- config/routes.rb | 7 +++++-- spec/requests/tags_spec.rb | 4 ++-- 10 files changed, 62 insertions(+), 24 deletions(-) create mode 100644 app/assets/stylesheets/tags.css.css delete mode 100644 app/views/tags/autocomplete.html.haml diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index 766138ee..c6ba8b46 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -270,6 +270,20 @@ input.ssh_project_url { } } +#projects-list .small-tags a{ + font-size: 9px; + + display: inline-block; + padding: 2px 3px 1px 3px; + margin: 0px 3px 0px 0px; + border-radius: 2px; + background-color: #3b6bce; + color: #FFF; + text-shadow: none; + font-weight: bold; +} + + .clear { clear: both; } diff --git a/app/assets/stylesheets/tags.css.css b/app/assets/stylesheets/tags.css.css new file mode 100644 index 00000000..0dfcc4fc --- /dev/null +++ b/app/assets/stylesheets/tags.css.css @@ -0,0 +1,16 @@ +.tags-list { + padding : 0px 10px 10px 10px; + +} + +.tags-list a { + display: inline-block; + padding: 8px 11px 8px 11px; + margin: 1px 5px 0px 0px; + border-radius: 4px; + border: 1px solid #d0e1ff; + background-color: #d0e1ff; + color: #0f326d; + font-weight: bold; + font-size: 14px; +} \ No newline at end of file diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 067245c4..09661685 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -10,7 +10,9 @@ class ProjectsController < ApplicationController before_filter :require_non_empty_project, :only => [:blob, :tree] def index - @projects = current_user.projects.all + source = current_user.projects + source = source.tagged_with(params[:tag]) unless params[:tag].blank? + @projects = source.all end def new diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 6ec3226a..913bc62b 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -1,15 +1,11 @@ class TagsController < ApplicationController def index - end - - def autocomplete - tags = Project.tag_counts.limit 8 - tags = tags.where('name like ?', "%#{params[:term]}%") unless params[:term].blank? - tags = tags.map {|t| t.name} + @tags = Project.tag_counts.order('count DESC') + @tags = @tags.where('name like ?', "%#{params[:term]}%") unless params[:term].blank? respond_to do |format| - format.json { render json: tags} + format.html + format.json { render json: @tags.limit(8).map {|t| t.name}} end end - end diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 059ee40c..2ddfda48 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -57,11 +57,8 @@ $(function(){ var tag_field = $('#tag_field').tagify(); - tag_field.tagify('inputField').autocomplete({ - source: '/tags/autocomplete.json', - position: { of: tag_field.tagify('containerDiv') }, - close: function(event, ui) { tag_field.tagify('add'); }, + source: '/tags.json' }); @@ -70,6 +67,4 @@ tag_field.val( tag_field.tagify('serialize') ); return true; }); - - }) diff --git a/app/views/projects/_list.html.haml b/app/views/projects/_list.html.haml index 65f0b7fd..7976b11f 100644 --- a/app/views/projects/_list.html.haml +++ b/app/views/projects/_list.html.haml @@ -10,7 +10,12 @@ - @projects.each do |project| %tr{ :class => "project", :url => project_path(project) } - %td= project.name + %td + = project.name + .small-tags + - project.tag_list.each do |tag| + = link_to tag, "/tags/#{tag}" + %td= truncate project.url_to_repo %td= project.code %td= check_box_tag "read", 1, project.readers.include?(current_user), :disabled => :disabled diff --git a/app/views/tags/autocomplete.html.haml b/app/views/tags/autocomplete.html.haml deleted file mode 100644 index e5c86e7e..00000000 --- a/app/views/tags/autocomplete.html.haml +++ /dev/null @@ -1,2 +0,0 @@ -%h1 Tags#autocomplete -%p Find me in app/views/tags/autocomplete.html.haml \ No newline at end of file diff --git a/app/views/tags/index.html.haml b/app/views/tags/index.html.haml index 7bf17b5e..c83d62c7 100644 --- a/app/views/tags/index.html.haml +++ b/app/views/tags/index.html.haml @@ -1,2 +1,11 @@ -%h1 Tags#index -%p Find me in app/views/tags/index.html.haml \ No newline at end of file +- content_for(:body_class, "projects-page") +- content_for(:page_title) do + .grid_4 + %h2 + Tags + + + .tags-list + - @tags.all.each do |tag| + = link_to "#{tag.name}(#{tag.count})", "/tags/#{tag.name}" + diff --git a/config/routes.rb b/config/routes.rb index c6b2d8b1..d4e27965 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,8 @@ Gitlab::Application.routes.draw do - get "tags/index" - get "tags/autocomplete" + + get 'tags'=> 'tags#index' + get 'tags/:tag' => 'projects#index' + namespace :admin do resources :users @@ -23,6 +25,7 @@ Gitlab::Application.routes.draw do resources :projects, :only => [:new, :create, :index] resources :keys + devise_for :users resources :projects, :except => [:new, :create, :index], :path => "/" do diff --git a/spec/requests/tags_spec.rb b/spec/requests/tags_spec.rb index 43d7a0ff..94a034da 100644 --- a/spec/requests/tags_spec.rb +++ b/spec/requests/tags_spec.rb @@ -11,13 +11,13 @@ describe "Tags" do # end - describe "GET '/tags/autocomplete'" do + describe "GET '/tags.json'" do before do @project = Factory :project @project.add_access(@user, :read) @project.tag_list = 'demo1' @project.save - visit '/tags/autocomplete.json' + visit '/tags.json' end From 62112dc0c7eae8d8c8e3d55fc13d3d58b7588899 Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Sat, 5 Nov 2011 22:16:13 +0200 Subject: [PATCH 173/176] add tags to project list --- app/assets/stylesheets/projects.css.scss | 14 -------------- app/assets/stylesheets/tags.css.css | 18 ++++++++++++++++-- app/views/projects/_tile.html.haml | 5 +++++ 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index c6ba8b46..766138ee 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -270,20 +270,6 @@ input.ssh_project_url { } } -#projects-list .small-tags a{ - font-size: 9px; - - display: inline-block; - padding: 2px 3px 1px 3px; - margin: 0px 3px 0px 0px; - border-radius: 2px; - background-color: #3b6bce; - color: #FFF; - text-shadow: none; - font-weight: bold; -} - - .clear { clear: both; } diff --git a/app/assets/stylesheets/tags.css.css b/app/assets/stylesheets/tags.css.css index 0dfcc4fc..afd458fd 100644 --- a/app/assets/stylesheets/tags.css.css +++ b/app/assets/stylesheets/tags.css.css @@ -8,9 +8,23 @@ padding: 8px 11px 8px 11px; margin: 1px 5px 0px 0px; border-radius: 4px; - border: 1px solid #d0e1ff; - background-color: #d0e1ff; + border: 1px solid #72bbdf; + background-color: #72bbdf; color: #0f326d; font-weight: bold; font-size: 14px; +} + + +.small-tags a{ + font-size: 9px; + + display: inline-block; + padding: 2px 3px 1px 3px; + margin: 0px 3px 0px 0px; + border-radius: 2px; + background-color: #72bbdf; + color: #FFF; + text-shadow: none; + font-weight: bold; } \ No newline at end of file diff --git a/app/views/projects/_tile.html.haml b/app/views/projects/_tile.html.haml index 7c0b8679..cc891f63 100644 --- a/app/views/projects/_tile.html.haml +++ b/app/views/projects/_tile.html.haml @@ -12,6 +12,11 @@ %span Last Activity: - last_note = project.notes.last = last_note ? last_note.created_at.stamp("24 Aug, 2011") : "Never" + + %p.small-tags + - project.tag_list.each do |tag| + = link_to tag, "/tags/#{tag}" + .buttons %a.browse-code.button.yellow{:href => tree_project_path(project)} Browse code %a.commits.button.green{:href => project_commits_path(project)} Commits From 671e261e900491ae29e118ac12f3ca9328109ab8 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Sun, 6 Nov 2011 15:52:23 +0200 Subject: [PATCH 174/176] lil design changes --- app/assets/stylesheets/projects.css.scss | 4 ++++ app/views/issues/_issues.html.haml | 1 - app/views/issues/_show.html.haml | 14 ++++++++------ app/views/notes/_show.html.haml | 10 +++++----- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss index c4b5de8a..c31f795a 100644 --- a/app/assets/stylesheets/projects.css.scss +++ b/app/assets/stylesheets/projects.css.scss @@ -663,6 +663,10 @@ table.highlighttable pre{ } } +.cgray { color:gray; } +.cred { color:#D12F19; } +.cgreen { color:#44aa22; } + body.project-page #notes-list .note {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} body.project-page #notes-list .note {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} body.project-page #notes-list .note img{float: left; margin-right: 10px;} diff --git a/app/views/issues/_issues.html.haml b/app/views/issues/_issues.html.haml index a6a38e69..d758fed5 100644 --- a/app/views/issues/_issues.html.haml +++ b/app/views/issues/_issues.html.haml @@ -6,7 +6,6 @@ %th ID %th Title %th Closed? - %th - @issues.critical.each do |issue| = render(:partial => 'show', :locals => {:issue => issue}) diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml index 05208d09..72b99b04 100644 --- a/app/views/issues/_show.html.haml +++ b/app/views/issues/_show.html.haml @@ -14,6 +14,14 @@ %span.tag.high critical - if issue.today? %span.tag.today today + + .right + - if can?(current_user, :admin_issue, @project) || issue.author == current_user + = link_to 'Edit', edit_project_issue_path(@project, issue), :class => "cgray", :remote => true + - if can?(current_user, :admin_issue, @project) || issue.author == current_user +   + = link_to 'Destroy', [@project, issue], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "cred delete-issue negative", :id => "destroy_issue_#{issue.id}" + -#- if issue.author == current_user -#%span.tag.yours yours -#- if issue.notes.count > 0 @@ -27,9 +35,3 @@ = hidden_field_tag :status_only, true - else = check_box_tag "closed", 1, issue.closed, :disabled => true - %td - - if @view_mode == :fluid - - if can?(current_user, :admin_issue, @project) || issue.author == current_user - = link_to 'Edit', edit_project_issue_path(@project, issue), :class => "lbutton positive", :remote => true - - if can?(current_user, :admin_issue, @project) || issue.author == current_user - = link_to 'Destroy', [@project, issue], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-issue negative", :id => "destroy_issue_#{issue.id}" diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_show.html.haml index 5d766291..27cb3874 100644 --- a/app/views/notes/_show.html.haml +++ b/app/views/notes/_show.html.haml @@ -2,16 +2,16 @@ = image_tag gravatar_icon(note.author.email), :class => "left", :width => 40, :style => "padding-right:5px;" %div.note-author %strong= note.author_name - %cite + %cite.cgray = time_ago_in_words(note.updated_at) ago - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) - = link_to 'Remove', [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "lbutton delete-note right negative" + = link_to "Remove", [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "cred delete-note right" %div.note-title = markdown(note.note) - if note.attachment.url - Attachment: - = link_to note.attachment_identifier, note.attachment.url, :target => "_blank" - %br + .right + %span.file + = link_to note.attachment_identifier, note.attachment.url, :target => "_blank" .clear From 526752479d7a85596259fdee6f55cdefbbc3c1d6 Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Sun, 6 Nov 2011 20:48:21 +0200 Subject: [PATCH 175/176] correct html on project page --- app/views/projects/index.html.haml | 32 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/app/views/projects/index.html.haml b/app/views/projects/index.html.haml index a35ead82..ba860571 100644 --- a/app/views/projects/index.html.haml +++ b/app/views/projects/index.html.haml @@ -1,18 +1,20 @@ - content_for(:body_class, "projects-page") - content_for(:page_title) do - .grid_4 - - if current_user.can_create_project? - %a.grey-button.right{:href => new_project_path} Create new project - %h2.icon - %span - Projects + .container_4 + .grid_4 + - if current_user.can_create_project? + %a.grey-button.right{:href => new_project_path} Create new project + %h2.icon + %span + Projects -- unless @projects.empty? - %div{:class => "tile", :style => view_mode_style("tile")} - = render "tile" - %div{:class => "list", :style => view_mode_style("list")} - = render "list" -- else - %center.prepend-top - %h2 - %cite Nothing here + %div.clear + - unless @projects.empty? + %div{:class => "tile", :style => view_mode_style("tile")} + = render "tile" + %div{:class => "list", :style => view_mode_style("list")} + = render "list" + - else + %center.prepend-top + %h2 + %cite Nothing here From 1d1b5186c3cbf85fb8f539b241ced29c314a3ff2 Mon Sep 17 00:00:00 2001 From: Aleksei Kvitinskii Date: Sun, 6 Nov 2011 21:43:34 +0200 Subject: [PATCH 176/176] fix small bug in top menu (buttons change height on press in chrome) --- app/assets/stylesheets/style.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/style.scss b/app/assets/stylesheets/style.scss index 29e6058d..ec403eba 100755 --- a/app/assets/stylesheets/style.scss +++ b/app/assets/stylesheets/style.scss @@ -323,6 +323,7 @@ header nav{border-radius: 4px; box-shadow: 0 1px 2px black; width: 294px; margin background-image: -moz-linear-gradient(#595d63 6.6%, #31363e); background-image: -o-linear-gradient(#595d63 6.6%, #31363e); margin-top: 2px; + height:30px } header nav a{padding: 8px 12px 8px 34px; display: inline-block; color: #D6DADF; border-right: 1px solid #31363E; position: relative; box-shadow: 1px 0 0 rgba(255,255,255,.1); margin: 0} header nav a span{width: 20px; height: 20px; display: inline-block; background: red; position: absolute; left: 8px; top: 6px;}