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 0000000000..c83fcb6871 --- /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 0000000000..1019a70aa1 --- /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 0000000000..53607ea52b --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--colour diff --git a/.rvmrc b/.rvmrc new file mode 100644 index 0000000000..8ad3b66d53 --- /dev/null +++ b/.rvmrc @@ -0,0 +1 @@ +rvm use 1.9.2-p290 diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000000..78d50e03e3 --- /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 0000000000..a431f5025e --- /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 0000000000..b389f143c6 --- /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 0000000000..7cecc2485f --- /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 0000000000..3ac8c6c625 --- /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 0000000000..35b2f05cbb --- /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 0000000000..f374f6662e --- /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 0000000000..93a51f7c38 --- /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 0000000000..01e3b41652 --- /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 0000000000..a62e9330ff --- /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 0000000000..761567942f --- /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 0000000000..761567942f --- /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 0000000000..14c9064f7f --- /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 0000000000..d61d75f96a --- /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 0000000000..6a3e394b40 --- /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 0000000000..d61d75f96a --- /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 0000000000..41451a0cab --- /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 1f50766054..6da5dea8bf 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 0000000000..11e18eb779 --- /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 05cb98e73c..31f9369a45 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 bc15d8e2c1..2ea79dcc2c 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 0000000000..1b680d87bd --- /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 d0a40eb18e..1703c00d5e 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 0000000000..5a6ffa4f91 --- /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 89a906f047..c389fd4a90 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 0000000000..236b6c8c23 --- /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 0a2c45f128..9a5970b583 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 3c07976d24..3366b87816 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 0000000000..d51afc3999 --- /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 baa1f14fe0..9dbe57d223 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 b81ba6bb4d..fe4b72da68 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 0000000000..571e2b063c --- /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 0000000000..483ff42cbb --- /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 0000000000..f81c0b8bc6 --- /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 0000000000..6e5dbde5bb --- /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 0000000000..f81c0b8bc6 --- /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 0000000000..d29e0f8c7a --- /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 acf92536e3..9ee3f0d06f 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 0000000000..9b0bf201cb --- /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 0000000000..511a6793f4 --- /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 0000000000..d378d225ec --- /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 ed37dbbb92..a819697640 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 ea055d1bcd..cc0cd4e5e8 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 0000000000..2a63584e42 --- /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 a725a49c2d..a9b69c63db 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 0000000000..00ae58dad8 --- /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 f1b546684f..4e7de84fc5 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 4eebb83aa1..5a3ba3a7f4 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 147aaafb85..a2c9149d06 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 9ba33c1ef8..4ebcfbefea 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 4e7de84fc5..b79e571819 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 1201a85762..aa8461661e 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 7dea76edb3..6d7de6e6ab 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 2866d1a735..047c6cb7d9 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 6da5dea8bf..cf8e1ebe66 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 1703c00d5e..46425664d6 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 5a6ffa4f91..b31fe6836a 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 e00cc36c0e..5fb2710dad 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 9a5970b583..b822f6300c 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 a9b69c63db..90f88d8808 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 3c923870e8..a27eb1ca33 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 953b535698..dcdfa6d50f 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 9b1b923eaa..556cdc1c1c 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 d51afc3999..0a54fee7e2 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 23609023c5..b2d594c904 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 2a63584e42..9dab72ca7d 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 d5500aca8e..23feecf407 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 d7eec2898b..dccb7df369 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 0000000000..5b9a34c0a9 --- /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 9d1d4b941c..040c2f2805 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 0000000000..1e4a6bb2b2 --- /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 0000000000..5b9a34c0a9 --- /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 ccb159f128..8eaf968c80 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 040c2f2805..c93a47239f 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 47cff1d883..0af548ff85 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 3366b87816..f51bd9b3ad 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 9dbe57d223..00ca98efa0 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 a9eef96cd3..cab7da2d43 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 e8f1c3925c..c6dcafab31 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 d570dff463..4556c8ba77 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 f89fb9f899..a02464fae7 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 fe4b72da68..e281b93b28 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 0fd9c8ead1..b8e660d72f 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 c6dcafab31..3fc1bf5f9a 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 3fc1bf5f9a..5a558bde64 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 b8e660d72f..9daa44aa30 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 2ea79dcc2c..4739a469e7 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 5a558bde64..7469b05b0b 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 4556c8ba77..02e1df5d0b 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 a02464fae7..71fd9dcd13 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 0000000000..812be93c1a --- /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 0000000000..2191ed954a --- /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 9daa44aa30..25cd7b947c 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 7469b05b0b..6bcc14b5b2 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 2825a6a979..a1bac06240 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 9fa8958772..29dcbbce0a 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 4739a469e7..8d5454357f 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 6bcc14b5b2..8ce3ca97cc 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 2191ed954a..166123508e 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 25cd7b947c..ff6078c15a 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 8d5454357f..860523b046 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 02e1df5d0b..4a6923afd0 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 166123508e..03f723da87 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 037aeccb22..b2466d932c 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 d29e0f8c7a..bb444efec7 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 666c6309dc..c8477729a9 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 0972f006db..7736599e7e 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 17be416fa1..aa9df298e1 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 b1d110bec2..aee73c38ee 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 12737ba814..ef23a1692a 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 9ee3f0d06f..8a40a8fef8 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 0000000000..b0ffe5366a --- /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 a819697640..6408792f9a 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 77abe2ca93..32fb90a317 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 07fdc4abdc..5838f63b40 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 bdc10633a3..96e2d16aff 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 01e3b41652..024dfe1182 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 860523b046..517886722c 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 8ce3ca97cc..dc94bae2c7 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 5a3ba3a7f4..94a1bd1b99 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 2c46689b1e..cec1fe2834 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 8eaf968c80..ca56a2450a 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 c93a47239f..2d110162ec 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 2b0a6d2ebc..ee9f9ffaa4 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 0af548ff85..15371dbce2 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 812be93c1a..e435ea30f0 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 03f723da87..1af7fe3bb2 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 479bb3cfc5..d3dcb3530a 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 c389fd4a90..0895eb0d1b 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 0a54fee7e2..119b69a452 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 dff99bf12f..73652aaf9f 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 3463bfc543..ae95d48317 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 bb444efec7..899950b7c3 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 0000000000..8f1329a660 --- /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 6e7460ed99..40bf26735c 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 200977877b..5e47b26922 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 cab7da2d43..59b3f2a2c8 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 aa8461661e..96acfba144 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 6d7de6e6ab..9084fa2f71 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.2 +1.1.0 diff --git a/update.rb b/update.rb index dccb7df369..b81a408888 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 dc94bae2c7..5ccfe4bb34 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 71fd9dcd13..e3dabce479 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 f51bd9b3ad..d70b18e793 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 ff6078c15a..85019ecbe5 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 d3dcb3530a..ed22478c92 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 a1bac06240..945c1ea26f 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 5ccfe4bb34..54d19af751 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 523793e7ca..77a00659ac 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 2aa894aa87..5ba3445975 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 119b69a452..95d6a07d54 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 ae95d48317..41a2287aa8 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 a891747155..4c60facde8 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 8f1329a660..4bd7100353 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 40bf26735c..e57121a3e2 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 e281b93b28..59f2533ea7 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 6d310768af..b9a68e6cfb 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 0000000000..d07c54f8b6 --- /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 0000000000..6f05c05da7 --- /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 6408792f9a..cc805990a8 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 db7513ae95..dd92febf70 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 09f64f9e3c..462647ab85 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 6f05c05da7..6e506c1cf9 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 200977877b..74ffe15aaf 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 9c5a6da09e..cfff6bf8bc 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 94d1abe87c..cfff6bf8bc 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 a118cb5d6f..0000000000 --- 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 b81a408888..0000000000 --- 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 73652aaf9f..c88e54307e 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 d70b18e793..1dd04e1fcb 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 c88e54307e..2807e0903d 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 0000000000..922c35990a --- /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 0000000000..b20aa8afe4 --- /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 6ed8653d76..0c62743d8e 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 517886722c..8caa2810e7 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 1dd04e1fcb..5262e55245 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 5fb2710dad..84addf8d7b 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 dd92febf70..ec0af3214a 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 77a00659ac..ad15fc8331 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 5ba3445975..a881b05e97 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 cf8e1ebe66..7b8c7cb503 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 6f4548a806..53c4fe668d 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 51a4dd459d..59e1f12c52 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 8a40a8fef8..5787922461 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 79fdf5efbb..d3582d1679 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 59b3f2a2c8..1dd87c0abe 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 1dd87c0abe..92d32d8bf7 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 bdc10633a3..96e2d16aff 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 aa8461661e..96acfba144 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 6d7de6e6ab..9084fa2f71 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.2 +1.1.0 diff --git a/update.rb b/update.rb index dccb7df369..b81a408888 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 dc94bae2c7..5ccfe4bb34 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 71fd9dcd13..e3dabce479 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 f51bd9b3ad..d70b18e793 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 ff6078c15a..85019ecbe5 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 d3dcb3530a..ed22478c92 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 a1bac06240..945c1ea26f 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 5ccfe4bb34..54d19af751 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 523793e7ca..77a00659ac 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 2aa894aa87..5ba3445975 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 119b69a452..95d6a07d54 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 ae95d48317..41a2287aa8 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 a891747155..4c60facde8 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 8f1329a660..4bd7100353 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 40bf26735c..e57121a3e2 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 e281b93b28..59f2533ea7 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 6d310768af..b9a68e6cfb 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 0000000000..d07c54f8b6 --- /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 0000000000..6f05c05da7 --- /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 6408792f9a..cc805990a8 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 db7513ae95..dd92febf70 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 09f64f9e3c..462647ab85 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 6f05c05da7..6e506c1cf9 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 5e47b26922..3e604a0f78 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 9c5a6da09e..cfff6bf8bc 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 94d1abe87c..cfff6bf8bc 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 a118cb5d6f..0000000000 --- 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 b81a408888..0000000000 --- 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 73652aaf9f..c88e54307e 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 d70b18e793..1dd04e1fcb 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 c88e54307e..2807e0903d 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 0000000000..922c35990a --- /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 0000000000..b20aa8afe4 --- /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 6ed8653d76..0c62743d8e 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 517886722c..8caa2810e7 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 1dd04e1fcb..5262e55245 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 5fb2710dad..84addf8d7b 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 dd92febf70..ec0af3214a 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 3e604a0f78..4016ebba5b 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 d190358640..11b04a3ba4 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 41a2287aa8..b5b1821388 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 b79e571819..f1b546684f 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 94a1bd1b99..3ed70f1cff 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 a2c9149d06..0ba4261847 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 e435ea30f0..36f4b636d2 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 1af7fe3bb2..36f1435b15 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 4ebcfbefea..538d2cc6e6 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 4bd7100353..9231da6ff9 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 0000000000..c175fa0cc2 --- /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 3ed70f1cff..9982306547 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 0ba4261847..3beeada8c8 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 36f4b636d2..3157c35686 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 36f1435b15..67f3449bd9 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 538d2cc6e6..53c05d5a42 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 c175fa0cc2..e09dbdaf8e 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 ec0af3214a..650ed4497f 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 8caa2810e7..3e7633a6ae 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 cf8e1ebe66..757ada9476 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 556cdc1c1c..904965ac7e 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 71acdba189..eae0ee0f52 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 d3e2194034..42e8371a0b 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 30157257ff..fcac006e81 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 0000000000..676eaaf8c1 --- /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 cc805990a8..21c224d4a9 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 b20aa8afe4..67033adea7 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 71338a6181..93cf19b603 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 53c4fe668d..7e4694efa4 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 d3582d1679..b7f4d41128 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 ad15fc8331..77a00659ac 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 a881b05e97..5ba3445975 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 3e7633a6ae..2e97bddef9 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 7e4694efa4..73d446be2e 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 59e1f12c52..51a4dd459d 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 2e97bddef9..c170053703 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 14c9064f7f..d92b7a34b0 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 d61d75f96a..957fe4d888 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 74f0e643c2..87be2f0730 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 42fe63db2b..db803ee40a 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 31f9369a45..fc14949a19 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 37cfbd0557..481adf5a2a 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 3e7633a6ae..6fd5150e33 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 05ad267fad..d2fbbcd496 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 e9ad1e5598..f60330f73c 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 047c6cb7d9..816c4c55b8 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 757ada9476..56d711dbca 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 b0249375b8..d3c93b5fff 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 46425664d6..ad9531e077 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 c8477729a9..a0078f0e0a 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 54d19af751..481e02fd23 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 b31fe6836a..d9a6ab2a1b 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 84addf8d7b..48e7e9b9c4 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 0895eb0d1b..599d1e5c5c 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 f1b546684f..bc95f916d1 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 4a6923afd0..75ab737cda 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 b822f6300c..5ab70650d8 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 904965ac7e..ca1c5eaf52 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 29dcbbce0a..1559b5bdf5 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 e3dabce479..9dcdbb5511 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 5262e55245..ef7f4e4654 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 95d6a07d54..0f488a8c94 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 7736599e7e..c90cf49f63 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 7b723cb802..60e2458848 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 6891894122..fc2e63241a 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 bbd7a6c0af..5aa4b59787 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 bd30c7b0e6..29d1160ce5 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 aa9df298e1..51b5d5c76e 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 cec6e3e188..b188d2ab32 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 aee73c38ee..5bc5bf9ab8 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 2807e0903d..e385d9ddf3 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 e4c9cc6e83..f1e4c7eb3f 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 67033adea7..db71c387ec 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 cec1fe2834..9831bb2957 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 b7ae403caa..5399a96157 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 e75c937101..ff76588c14 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 eab783a4c9..33b1120f99 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 c6cdcfe51c..b787e648ca 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 42e8371a0b..11e4c38e08 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 fcac006e81..afcd2b6e7c 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 6f4548a806..46a15ef169 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 199c80c861..29b6f3f7b8 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 5b9a34c0a9..ae2ff32cc6 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 c365c3f5d5..30fca38c38 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 416ae8f8f9..279b125f53 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 4b6eb2b500..4011485c55 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 047f708b6d..07de8de4c2 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 ca56a2450a..14e74fa694 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 2d110162ec..e7cc236075 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 15371dbce2..a04130e8a7 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 213a73796c..1a5a603a59 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 969ea7e529..2d3abf2e55 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 242c97bf25..7d8e215609 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 c9fdae1267..a2bd5a7660 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 00ca98efa0..164f1d45f3 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 aec61ffbbe..65f0b7fd5b 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 f80f28a8bb..9e199183b1 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 3157c35686..b34470d674 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 bb9063369c..4001c7a255 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 4c60facde8..ffc1ebfa28 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 888a72b681..4b9457c161 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 60cbd19916..eb08adb1dd 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 ed22478c92..63c9613a85 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 5b9a34c0a9..ae2ff32cc6 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 571e2b063c..7a34ae8e03 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 6e5dbde5bb..fe5e617044 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 b9a68e6cfb..88260cca53 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 d07c54f8b6..4a093ee1d5 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 7ebe452396..d8094817c0 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 9231da6ff9..1a7e6361c0 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 8a40a8fef8..21a0729c33 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 3083e74245..01869a9e21 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 23feecf407..4eabe249c1 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 e09dbdaf8e..411809f05e 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 151e0ce53c..611e584f14 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 e57121a3e2..f43e2edd20 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 9d9811a5bf..16248edab5 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 29e552b147..5edef358ab 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 b2d594c904..e0559ab666 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 8515f19b2f..6522b825e1 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 20bd41adc2..5b16ad3682 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 8eb8ee80f6..f80294639f 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 0c62743d8e..7bce57e8bb 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 32fb90a317..d66b1c251f 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 d6a4d02b6e..c15391619c 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 ea42337f93..2e491496a7 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 e36ee4411f..fd8703ec06 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 8d9cbcae2a..67cfde5faf 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 743f9f08ce..27b6019676 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 522fe51824..c424f4fc3c 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 cd7314f981..79bb03f53b 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 95eb2f35d7..9ebad39473 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 79fdf5efbb..8c090d7fb3 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 316115f923..6ce22b3088 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 5838f63b40..eca1c12e80 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 90f88d8808..1d42c5e7c5 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 945c1ea26f..e1e9773c85 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 5b4facb17d..bf3ca167d3 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 4e3176bbdc..fd49ffaab5 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 a7387f9326..bb734bdab2 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 00ae58dad8..d4811958db 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 650ed4497f..d655551814 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 bd4d204779..d1cea6d86d 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 a27eb1ca33..b75a1779a8 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 0c2545e338..aa7f23d80c 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 462647ab85..a700c8b94d 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 dcdfa6d50f..e0672166e9 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 a2e94ac109..118b9b2a0b 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 024dfe1182..41c69119df 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 41c69119df..86887fddef 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 db803ee40a..777f3fc189 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 85019ecbe5..566217859e 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 77a00659ac..28168095b3 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 5ba3445975..01ec37e1ba 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 0000000000..0d94b33376 --- /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 21c224d4a9..44b9375ad0 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 236b6c8c23..cd7b03593c 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 0f488a8c94..acffc76cf0 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 7a34ae8e03..2c9680c028 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 483ff42cbb..ddfba6bf80 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 899950b7c3..bfa1bf456e 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 28168095b3..2f3e870cb6 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 01ec37e1ba..1f40f712af 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 cd7b03593c..6a91d61672 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 2c9680c028..5cd0f74a0b 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 acffc76cf0..44cb88872a 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 fe5e617044..3f2610004b 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 44cb88872a..b67db60b78 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 59f2533ea7..0b8751c93c 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 3eb99da61e..184307d000 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 4308e08ea8..0cd7af67f1 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 9a4fd4e458..3481c6d61e 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 77a00659ac..46320d221f 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 5ba3445975..44faaad7b7 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 5575261959..a71136398f 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 bca9bfebbf..8ae32bc661 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 e9ad1e5598..f6304e15ce 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 db71c387ec..1ef4a3c8a6 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 afcd2b6e7c..ebcaae29ef 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 9dcdbb5511..645bc7cec1 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 14e74fa694..86f0b779ad 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 0000000000..d762d361ae --- /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 21c224d4a9..8dd75e7500 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 d762d361ae..1bcf4b72bc 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 8dd75e7500..9c99e5328e 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 56042fa244..a70c65d47c 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 29b6f3f7b8..58bebe9b3d 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 30fca38c38..137dba3cc7 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 ca1c5eaf52..9fb7ef3060 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 eae0ee0f52..80f19d627f 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 ebcaae29ef..9cce287133 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 58bebe9b3d..eb972d33ab 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 0000000000..15d96c30b4 --- /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 2f3e870cb6..28168095b3 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 1f40f712af..01ec37e1ba 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 b67db60b78..5c61cf1c54 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 bfa1bf456e..757cdb11e0 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 9dab72ca7d..037287a992 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 d4811958db..ee4f90e602 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 60fc118c60..fc040ce08c 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 83ccebd89b..83df35b52a 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 ee9f9ffaa4..1907e9cc0a 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 f9c7592bd9..bde9aa5d15 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 26e4a5734c..d0fad8ed64 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 9cce287133..94cc03d17a 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 eb972d33ab..c61052839f 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 15d96c30b4..c151a9317f 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 9c99e5328e..e4f7379c37 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 cc0cd4e5e8..36aa4fc945 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 184f82931b..b13e43adc6 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 93a51f7c38..d6f1a9088f 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 07de8de4c2..e6f36e3fd0 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 5f95e1133a..bac472a2fb 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 411809f05e..32706acb61 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 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 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 ced0bf3bd7..7c0b8679c0 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 45187b444f..a35ead82f7 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 83071891be..79b97ed759 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 d9a6ab2a1b..54ad6019f7 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 48e7e9b9c4..8a4e32e59c 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 68f973dc7a..acf57bd1a2 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 e5184a7eb2..418a6e8230 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 9982306547..36225d37eb 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 452e13f8bd..92a382a91a 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 acf57bd1a2..619952f147 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 418a6e8230..e60dc7018d 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 c61052839f..371a803319 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 566217859e..ff3524370b 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 66db914a37..d8e043184f 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 92a382a91a..f8928b6fc3 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 11e4c38e08..a6a38e69d6 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 ec8fa89d74..ea72b25add 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 619952f147..b4b516315a 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 4001c7a255..d12ccac704 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 11b04a3ba4..2aca18e468 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 e6f36e3fd0..590e16a2f1 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 7bce57e8bb..bd83bc805f 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 0000000000..6940366af4 --- /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 0ff7030860..b5d6f1bcf6 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 9fb7ef3060..f649cacbac 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 645bc7cec1..3c59efefb1 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 36225d37eb..9761c65fa1 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 3227a447a6..3bd9145e1d 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 761826cae5..eb2122dff8 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 32706acb61..db6503557a 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 bac472a2fb..d45c32bdbc 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 d3de20dabd..8df7881cd2 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 8cc6325340..eedbf1167a 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 968fe58d39..3296466376 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 007e03cf5d..a33d9d5dd6 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 b4b516315a..f8d8221a81 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 0000000000..7870f053d4 --- /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 d8e043184f..4e4bcccc31 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 0bf38a5762..6d0edaceae 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 ef92953dab..3aa40c9960 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 f8928b6fc3..7999b94cf2 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 0000000000..f7712d3d05 --- /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 2aca18e468..f70bbb7a9b 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 97be566ffe..29e6058d52 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 6d0edaceae..070def961a 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 3aa40c9960..709848044f 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 a64aa3b551..6db1d3897c 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 8df7881cd2..e02dbe045c 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 eedbf1167a..030f19995e 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 a33d9d5dd6..2fd30dcd7b 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 f8d8221a81..ee6581ecdb 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 1559b5bdf5..5fe3073447 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 8da55b1095..f32c13f070 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 f66e832e4a..e557ee432e 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 befa1c6b14..de68f451e0 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 0000000000..16610615f9 --- /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 0000000000..f22d4c7119 --- /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 0000000000..d6c178f713 --- /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 7999b94cf2..b96501455f 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 f7712d3d05..60b17c7fa1 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 f70bbb7a9b..8fdf72f05f 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 86887fddef..b1e9573689 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 777f3fc189..e170dc0786 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 164f1d45f3..605a2f454a 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 13c4db0cc4..3d430f4c29 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 86887fddef..23845ea5c6 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 0000000000..71279fc423 --- /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 4e4bcccc31..06063b1637 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 e046add379..067245c482 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 e7cc236075..e33050b027 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 187d0a3c47..164733a56c 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 a04130e8a7..ffc80140ec 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 63c9613a85..2bc3150a1e 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 ae2ff32cc6..81417800c8 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 06063b1637..ba18bfa0ce 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 79b97ed759..f6af56f8aa 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 71c559a134..b6fd85b848 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 9831bb2957..ee31c0b8d3 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 371a803319..669784ba11 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 ae2ff32cc6..ee31c0b8d3 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 0000000000..f560f0bddc --- /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 e33050b027..4a5c3aab35 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 ffc80140ec..cf804493ca 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 2bc3150a1e..4f0ec41ee9 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 81417800c8..ee31c0b8d3 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 669784ba11..7321f635f9 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 ba18bfa0ce..766138ee3d 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 7321f635f9..8267a850ba 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 164733a56c..5d76629108 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 71279fc423..7acc81e5bf 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 070def961a..5c25d7d6c8 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 f6af56f8aa..fa0d0b570a 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 b6fd85b848..7ff1ccb3a6 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 067245c482..ef7eb9210d 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 f560f0bddc..c7ec9ed3f3 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 a62e9330ff..bef7ed74be 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 fa0d0b570a..79703cf104 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 9761c65fa1..2d3939937e 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 b96501455f..0dfb2cff2b 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 94daa396c5..0000000000 --- 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 0000000000..39b7108c50 --- /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 030f19995e..9022ecb11c 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 766138ee3d..0e1ad931d4 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 3bd9145e1d..b42b23de4e 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 0000000000..6ec3226a12 --- /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 605a2f454a..059ee40c87 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 0000000000..e5c86e7e71 --- /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 0000000000..7bf17b5e49 --- /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 d45c32bdbc..c6b2d8b1eb 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 0000000000..43d7a0ff48 --- /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 0e1ad931d4..c4b5de8a67 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 5c25d7d6c8..782612c0ae 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 94cc03d17a..05208d09ff 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 a70c65d47c..21e455b9ec 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 8267a850ba..dc4ab33800 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 c424f4fc3c..69a492e928 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 766138ee3d..c6ba8b465b 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 0000000000..0dfcc4fc8e --- /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 067245c482..0966168560 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 6ec3226a12..913bc62bd1 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 059ee40c87..2ddfda4862 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 65f0b7fd5b..7976b11fa1 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 e5c86e7e71..0000000000 --- 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 7bf17b5e49..c83d62c7ea 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 c6b2d8b1eb..d4e2796571 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 43d7a0ff48..94a034dabf 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 c6ba8b465b..766138ee3d 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 0dfcc4fc8e..afd458fd5d 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 7c0b8679c0..cc891f63bf 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 c4b5de8a67..c31f795a71 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 a6a38e69d6..d758fed538 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 05208d09ff..72b99b0400 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 5d76629108..27cb387489 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 a35ead82f7..ba860571fb 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 29e6058d52..ec403eba69 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;}