summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2015-11-17 17:01:28 +0100
committerDouwe Maan <douwe@gitlab.com>2015-11-17 17:01:28 +0100
commit0b540a0fadf172277639910023fcf8b713ad35aa (patch)
tree9efe6d84cebdca7bc31bcc0e6e2e3b7bdf2e3185 /app
parent3d50b99d016af91c06a40f7a8bf4c298e241220a (diff)
parentdf0110ba81a86b3e066c8b703e1c26d6d05a75da (diff)
downloadgitlab-ce-0b540a0fadf172277639910023fcf8b713ad35aa.tar.gz
Merge branch 'master' into dirceu/gitlab-ce-new-merge-request-from-file-edit
Diffstat (limited to 'app')
-rw-r--r--[-rwxr-xr-x]app/assets/fonts/SourceSansPro-Black.ttfbin148368 -> 289364 bytes
-rw-r--r--app/assets/fonts/SourceSansPro-BlackIt.ttfbin0 -> 103404 bytes
-rw-r--r--[-rwxr-xr-x]app/assets/fonts/SourceSansPro-Bold.ttfbin291424 -> 291424 bytes
-rw-r--r--app/assets/fonts/SourceSansPro-BoldIt.ttfbin0 -> 103608 bytes
-rw-r--r--[-rwxr-xr-x]app/assets/fonts/SourceSansPro-ExtraLight.ttfbin150528 -> 291652 bytes
-rw-r--r--app/assets/fonts/SourceSansPro-ExtraLightIt.ttfbin0 -> 104768 bytes
-rw-r--r--app/assets/fonts/SourceSansPro-It.ttfbin0 -> 104236 bytes
-rw-r--r--[-rwxr-xr-x]app/assets/fonts/SourceSansPro-Light.ttfbin293220 -> 293220 bytes
-rw-r--r--app/assets/fonts/SourceSansPro-LightIt.ttfbin0 -> 104616 bytes
-rw-r--r--[-rwxr-xr-x]app/assets/fonts/SourceSansPro-Regular.ttfbin293956 -> 293956 bytes
-rw-r--r--[-rwxr-xr-x]app/assets/fonts/SourceSansPro-Semibold.ttfbin292404 -> 292404 bytes
-rw-r--r--app/assets/fonts/SourceSansPro-SemiboldIt.ttfbin0 -> 104020 bytes
-rw-r--r--app/assets/images/auth_buttons/facebook_64.pngbin0 -> 2970 bytes
-rw-r--r--app/assets/images/logo.svg16
-rw-r--r--app/assets/javascripts/blob/edit_blob.js.coffee8
-rw-r--r--app/assets/javascripts/blob/new_blob.js.coffee8
-rw-r--r--app/assets/javascripts/calendar.js.coffee2
-rw-r--r--app/assets/javascripts/ci/build.coffee4
-rw-r--r--app/assets/javascripts/copy_to_clipboard.js.coffee21
-rw-r--r--app/assets/javascripts/dispatcher.js.coffee8
-rw-r--r--app/assets/stylesheets/framework/blocks.scss54
-rw-r--r--app/assets/stylesheets/framework/buttons.scss15
-rw-r--r--app/assets/stylesheets/framework/callout.scss6
-rw-r--r--app/assets/stylesheets/framework/common.scss31
-rw-r--r--app/assets/stylesheets/framework/files.scss5
-rw-r--r--app/assets/stylesheets/framework/header.scss4
-rw-r--r--app/assets/stylesheets/framework/layout.scss1
-rw-r--r--app/assets/stylesheets/framework/lists.scss4
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss1
-rw-r--r--app/assets/stylesheets/framework/mixins.scss10
-rw-r--r--app/assets/stylesheets/framework/selects.scss4
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss16
-rw-r--r--app/assets/stylesheets/framework/tables.scss10
-rw-r--r--app/assets/stylesheets/framework/timeline.scss6
-rw-r--r--app/assets/stylesheets/framework/typography.scss85
-rw-r--r--app/assets/stylesheets/pages/ci_projects.scss5
-rw-r--r--app/assets/stylesheets/pages/commits.scss9
-rw-r--r--app/assets/stylesheets/pages/diff.scss1
-rw-r--r--app/assets/stylesheets/pages/editor.scss2
-rw-r--r--app/assets/stylesheets/pages/events.scss16
-rw-r--r--app/assets/stylesheets/pages/help.scss4
-rw-r--r--app/assets/stylesheets/pages/issuable.scss21
-rw-r--r--app/assets/stylesheets/pages/issues.scss5
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss23
-rw-r--r--app/assets/stylesheets/pages/note_form.scss6
-rw-r--r--app/assets/stylesheets/pages/notes.scss5
-rw-r--r--app/assets/stylesheets/pages/profile.scss28
-rw-r--r--app/assets/stylesheets/pages/projects.scss72
-rw-r--r--app/assets/stylesheets/pages/runners.scss52
-rw-r--r--app/assets/stylesheets/pages/sherlock.scss33
-rw-r--r--app/assets/stylesheets/pages/snippets.scss60
-rw-r--r--app/assets/stylesheets/pages/tree.scss16
-rw-r--r--app/controllers/abuse_reports_controller.rb4
-rw-r--r--app/controllers/admin/application_controller.rb6
-rw-r--r--app/controllers/admin/application_settings_controller.rb3
-rw-r--r--app/controllers/admin/broadcast_messages_controller.rb2
-rw-r--r--app/controllers/admin/hooks_controller.rb2
-rw-r--r--app/controllers/admin/impersonation_controller.rb32
-rw-r--r--app/controllers/admin/users_controller.rb32
-rw-r--r--app/controllers/application_controller.rb27
-rw-r--r--app/controllers/ci/admin/runners_controller.rb1
-rw-r--r--app/controllers/ci/application_controller.rb8
-rw-r--r--app/controllers/ci/events_controller.rb21
-rw-r--r--app/controllers/ci/projects_controller.rb15
-rw-r--r--app/controllers/ci/runner_projects_controller.rb2
-rw-r--r--app/controllers/concerns/global_milestones.rb19
-rw-r--r--app/controllers/dashboard/milestones_controller.rb29
-rw-r--r--app/controllers/dashboard_controller.rb5
-rw-r--r--app/controllers/groups/application_controller.rb11
-rw-r--r--app/controllers/groups/avatars_controller.rb4
-rw-r--r--app/controllers/groups/group_members_controller.rb5
-rw-r--r--app/controllers/groups/milestones_controller.rb63
-rw-r--r--app/controllers/groups_controller.rb6
-rw-r--r--app/controllers/import/github_controller.rb4
-rw-r--r--app/controllers/import/google_code_controller.rb6
-rw-r--r--app/controllers/invites_controller.rb4
-rw-r--r--app/controllers/profiles/notifications_controller.rb2
-rw-r--r--app/controllers/profiles_controller.rb2
-rw-r--r--app/controllers/projects/application_controller.rb2
-rw-r--r--app/controllers/projects/blob_controller.rb2
-rw-r--r--app/controllers/projects/builds_controller.rb52
-rw-r--r--app/controllers/projects/ci_services_controller.rb10
-rw-r--r--app/controllers/projects/ci_web_hooks_controller.rb2
-rw-r--r--app/controllers/projects/commit_controller.rb47
-rw-r--r--app/controllers/projects/commits_controller.rb2
-rw-r--r--app/controllers/projects/compare_controller.rb6
-rw-r--r--app/controllers/projects/deploy_keys_controller.rb2
-rw-r--r--app/controllers/projects/hooks_controller.rb2
-rw-r--r--app/controllers/projects/issues_controller.rb13
-rw-r--r--app/controllers/projects/merge_requests_controller.rb12
-rw-r--r--app/controllers/projects/milestones_controller.rb6
-rw-r--r--app/controllers/projects/notes_controller.rb4
-rw-r--r--app/controllers/projects/project_members_controller.rb3
-rw-r--r--app/controllers/projects/releases_controller.rb31
-rw-r--r--app/controllers/projects/runners_controller.rb9
-rw-r--r--app/controllers/projects/services_controller.rb4
-rw-r--r--app/controllers/projects/snippets_controller.rb1
-rw-r--r--app/controllers/projects/tags_controller.rb20
-rw-r--r--app/controllers/projects_controller.rb40
-rw-r--r--app/controllers/search_controller.rb4
-rw-r--r--app/controllers/sherlock/application_controller.rb12
-rw-r--r--app/controllers/sherlock/file_samples_controller.rb7
-rw-r--r--app/controllers/sherlock/queries_controller.rb7
-rw-r--r--app/controllers/sherlock/transactions_controller.rb19
-rw-r--r--app/finders/groups_finder.rb57
-rw-r--r--app/finders/issuable_finder.rb114
-rw-r--r--app/finders/milestones_finder.rb12
-rw-r--r--app/helpers/appearances_helper.rb2
-rw-r--r--app/helpers/auth_helper.rb2
-rw-r--r--app/helpers/builds_helper.rb13
-rw-r--r--app/helpers/ci/gitlab_helper.rb19
-rw-r--r--app/helpers/ci_status_helper.rb11
-rw-r--r--app/helpers/clipboard_helper.rb8
-rw-r--r--app/helpers/diff_helper.rb7
-rw-r--r--app/helpers/events_helper.rb28
-rw-r--r--app/helpers/gitlab_markdown_helper.rb21
-rw-r--r--app/helpers/issues_helper.rb6
-rw-r--r--app/helpers/labels_helper.rb18
-rw-r--r--app/helpers/milestones_helper.rb2
-rw-r--r--app/helpers/notifications_helper.rb38
-rw-r--r--app/helpers/preferences_helper.rb8
-rw-r--r--app/helpers/projects_helper.rb6
-rw-r--r--app/helpers/search_helper.rb2
-rw-r--r--app/helpers/tab_helper.rb18
-rw-r--r--app/mailers/abuse_report_mailer.rb12
-rw-r--r--app/models/ability.rb5
-rw-r--r--app/models/application_setting.rb20
-rw-r--r--app/models/ci/application_setting.rb12
-rw-r--r--app/models/ci/build.rb46
-rw-r--r--app/models/ci/commit.rb79
-rw-r--r--app/models/ci/event.rb2
-rw-r--r--app/models/ci/project.rb29
-rw-r--r--app/models/ci/project_status.rb4
-rw-r--r--app/models/ci/runner.rb3
-rw-r--r--app/models/ci/runner_project.rb2
-rw-r--r--app/models/ci/service.rb2
-rw-r--r--app/models/ci/trigger.rb2
-rw-r--r--app/models/ci/trigger_request.rb2
-rw-r--r--app/models/ci/variable.rb2
-rw-r--r--app/models/ci/web_hook.rb2
-rw-r--r--app/models/commit.rb16
-rw-r--r--app/models/commit_status.rb44
-rw-r--r--app/models/concerns/issuable.rb11
-rw-r--r--app/models/concerns/mentionable.rb20
-rw-r--r--app/models/concerns/participable.rb32
-rw-r--r--app/models/concerns/sortable.rb10
-rw-r--r--app/models/event.rb2
-rw-r--r--app/models/generic_commit_status.rb33
-rw-r--r--app/models/global_label.rb17
-rw-r--r--app/models/global_milestone.rb (renamed from app/models/group_milestone.rb)30
-rw-r--r--app/models/group.rb3
-rw-r--r--app/models/hooks/project_hook.rb25
-rw-r--r--app/models/hooks/service_hook.rb25
-rw-r--r--app/models/hooks/system_hook.rb25
-rw-r--r--app/models/hooks/web_hook.rb25
-rw-r--r--app/models/issue.rb10
-rw-r--r--app/models/label.rb1
-rw-r--r--app/models/lfs_object.rb8
-rw-r--r--app/models/lfs_objects_project.rb8
-rw-r--r--app/models/merge_request.rb31
-rw-r--r--app/models/merge_request_diff.rb23
-rw-r--r--app/models/milestone.rb32
-rw-r--r--app/models/namespace.rb1
-rw-r--r--app/models/note.rb4
-rw-r--r--app/models/project.rb52
-rw-r--r--app/models/project_services/ci/hip_chat_message.rb2
-rw-r--r--app/models/project_services/ci/hip_chat_service.rb2
-rw-r--r--app/models/project_services/ci/mail_service.rb2
-rw-r--r--app/models/project_services/ci/slack_message.rb2
-rw-r--r--app/models/project_services/ci/slack_service.rb2
-rw-r--r--app/models/project_services/drone_ci_service.rb1
-rw-r--r--app/models/project_services/gitlab_ci_service.rb2
-rw-r--r--app/models/project_wiki.rb10
-rw-r--r--app/models/release.rb17
-rw-r--r--app/models/repository.rb86
-rw-r--r--app/models/user.rb77
-rw-r--r--app/services/archive_repository_service.rb2
-rw-r--r--app/services/ci/create_builds_service.rb14
-rw-r--r--app/services/ci/image_for_build_service.rb16
-rw-r--r--app/services/compare_service.rb4
-rw-r--r--app/services/create_tag_service.rb8
-rw-r--r--app/services/delete_tag_service.rb4
-rw-r--r--app/services/files/create_dir_service.rb11
-rw-r--r--app/services/files/create_service.rb11
-rw-r--r--app/services/git_push_service.rb9
-rw-r--r--app/services/issues/update_service.rb29
-rw-r--r--app/services/merge_requests/post_merge_service.rb10
-rw-r--r--app/services/merge_requests/refresh_service.rb88
-rw-r--r--app/services/merge_requests/update_service.rb47
-rw-r--r--app/services/milestones/group_service.rb26
-rw-r--r--app/services/notes/update_service.rb2
-rw-r--r--app/services/projects/create_service.rb2
-rw-r--r--app/services/projects/fork_service.rb2
-rw-r--r--app/services/system_hooks_service.rb72
-rw-r--r--app/services/system_note_service.rb27
-rw-r--r--app/uploaders/artifact_uploader.rb50
-rw-r--r--app/uploaders/attachment_uploader.rb19
-rw-r--r--app/uploaders/avatar_uploader.rb19
-rw-r--r--app/uploaders/file_uploader.rb19
-rw-r--r--app/uploaders/lfs_object_uploader.rb29
-rw-r--r--app/uploaders/uploader_helper.rb19
-rw-r--r--app/views/abuse_report_mailer/notify.html.haml11
-rw-r--r--app/views/abuse_report_mailer/notify.text.haml5
-rw-r--r--app/views/admin/abuse_reports/index.html.haml21
-rw-r--r--app/views/admin/application_settings/_form.html.haml20
-rw-r--r--app/views/admin/applications/show.html.haml37
-rw-r--r--app/views/admin/background_jobs/show.html.haml37
-rw-r--r--app/views/admin/deploy_keys/index.html.haml37
-rw-r--r--app/views/admin/identities/index.html.haml15
-rw-r--r--app/views/admin/labels/_form.html.haml4
-rw-r--r--app/views/admin/services/index.html.haml39
-rw-r--r--app/views/admin/users/_head.html.haml2
-rw-r--r--app/views/admin/users/_profile.html.haml (renamed from app/views/users/_profile.html.haml)4
-rw-r--r--app/views/admin/users/show.html.haml2
-rw-r--r--app/views/ci/admin/events/index.html.haml33
-rw-r--r--app/views/ci/admin/projects/index.html.haml23
-rw-r--r--app/views/ci/admin/runner_projects/index.html.haml2
-rw-r--r--app/views/ci/admin/runners/index.html.haml31
-rw-r--r--app/views/ci/admin/runners/show.html.haml34
-rw-r--r--app/views/ci/events/index.html.haml19
-rw-r--r--app/views/ci/lints/_create.html.haml50
-rw-r--r--app/views/ci/lints/show.html.haml16
-rw-r--r--app/views/ci/notify/build_fail_email.html.haml8
-rw-r--r--app/views/ci/notify/build_fail_email.text.erb2
-rw-r--r--app/views/ci/notify/build_success_email.html.haml8
-rw-r--r--app/views/ci/notify/build_success_email.text.erb2
-rw-r--r--app/views/ci/projects/index.html.haml20
-rw-r--r--app/views/ci/user_sessions/new.html.haml3
-rw-r--r--app/views/dashboard/groups/index.html.haml2
-rw-r--r--app/views/dashboard/milestones/index.html.haml6
-rw-r--r--app/views/dashboard/milestones/show.html.haml76
-rw-r--r--app/views/dashboard/snippets/index.html.haml26
-rw-r--r--app/views/doorkeeper/applications/index.html.haml30
-rw-r--r--app/views/doorkeeper/applications/show.html.haml38
-rw-r--r--app/views/doorkeeper/authorized_applications/index.html.haml25
-rw-r--r--app/views/events/_event_issue.atom.haml3
-rw-r--r--app/views/events/_event_merge_request.atom.haml3
-rw-r--r--app/views/events/_event_note.atom.haml2
-rw-r--r--app/views/events/_event_push.atom.haml2
-rw-r--r--app/views/explore/snippets/index.html.haml3
-rw-r--r--app/views/groups/edit.html.haml9
-rw-r--r--app/views/groups/group_members/index.html.haml9
-rw-r--r--app/views/groups/milestones/_milestone.html.haml2
-rw-r--r--app/views/groups/milestones/index.html.haml19
-rw-r--r--app/views/groups/milestones/new.html.haml48
-rw-r--r--app/views/groups/milestones/show.html.haml84
-rw-r--r--app/views/help/_shortcuts.html.haml8
-rw-r--r--app/views/import/bitbucket/status.html.haml81
-rw-r--r--app/views/import/fogbugz/new_user_map.html.haml37
-rw-r--r--app/views/import/fogbugz/status.html.haml67
-rw-r--r--app/views/import/github/status.html.haml67
-rw-r--r--app/views/import/gitlab/status.html.haml67
-rw-r--r--app/views/import/gitorious/status.html.haml67
-rw-r--r--app/views/import/google_code/status.html.haml81
-rw-r--r--app/views/layouts/_piwik.html.haml18
-rw-r--r--app/views/layouts/_search.html.haml6
-rw-r--r--app/views/layouts/ci/_nav_admin.html.haml18
-rw-r--r--app/views/layouts/ci/project.html.haml11
-rw-r--r--app/views/layouts/header/_default.html.haml9
-rw-r--r--app/views/layouts/nav/_group.html.haml4
-rw-r--r--app/views/layouts/nav/_group_settings.html.haml4
-rw-r--r--app/views/layouts/nav/_profile.html.haml4
-rw-r--r--app/views/layouts/nav/_project.html.haml10
-rw-r--r--app/views/layouts/nav/_project_settings.html.haml11
-rw-r--r--app/views/layouts/notify.html.haml9
-rw-r--r--app/views/notify/_note_message.html.haml2
-rw-r--r--app/views/notify/new_issue_email.html.haml2
-rw-r--r--app/views/notify/new_merge_request_email.html.haml2
-rw-r--r--app/views/notify/project_was_moved_email.text.erb2
-rw-r--r--app/views/profiles/_event_table.html.haml29
-rw-r--r--app/views/profiles/notifications/_settings.html.haml2
-rw-r--r--app/views/profiles/preferences/show.html.haml4
-rw-r--r--app/views/projects/_activity.html.haml5
-rw-r--r--app/views/projects/_files.html.haml6
-rw-r--r--app/views/projects/_last_commit.html.haml12
-rw-r--r--app/views/projects/_readme.html.haml13
-rw-r--r--app/views/projects/activity.html.haml2
-rw-r--r--app/views/projects/blob/_blob.html.haml31
-rw-r--r--app/views/projects/blob/_new_dir.html.haml2
-rw-r--r--app/views/projects/blob/_upload.html.haml6
-rw-r--r--app/views/projects/blob/show.html.haml3
-rw-r--r--app/views/projects/branches/_commit.html.haml4
-rw-r--r--app/views/projects/builds/_build.html.haml53
-rw-r--r--app/views/projects/builds/_header_title.html.haml1
-rw-r--r--app/views/projects/builds/index.html.haml41
-rw-r--r--app/views/projects/builds/show.html.haml46
-rw-r--r--app/views/projects/buttons/_dropdown.html.haml6
-rw-r--r--app/views/projects/buttons/_notifications.html.haml32
-rw-r--r--app/views/projects/buttons/_star.html.haml12
-rw-r--r--app/views/projects/ci_services/edit.html.haml1
-rw-r--r--app/views/projects/ci_services/index.html.haml3
-rw-r--r--app/views/projects/ci_settings/_form.html.haml7
-rw-r--r--app/views/projects/ci_settings/_no_runners.html.haml2
-rw-r--r--app/views/projects/ci_settings/edit.html.haml20
-rw-r--r--app/views/projects/ci_web_hooks/index.html.haml24
-rw-r--r--app/views/projects/commit/_ci_menu.html.haml6
-rw-r--r--app/views/projects/commit/_commit_box.html.haml8
-rw-r--r--app/views/projects/commit/builds.html.haml72
-rw-r--r--app/views/projects/commit/ci.html.haml67
-rw-r--r--app/views/projects/commit_statuses/_commit_status.html.haml34
-rw-r--r--app/views/projects/commits/_commit.html.haml6
-rw-r--r--app/views/projects/commits/_head.html.haml2
-rw-r--r--app/views/projects/commits/show.atom.builder2
-rw-r--r--app/views/projects/diffs/_diffs.html.haml6
-rw-r--r--app/views/projects/diffs/_file.html.haml4
-rw-r--r--app/views/projects/edit.html.haml29
-rw-r--r--app/views/projects/empty.html.haml85
-rw-r--r--app/views/projects/graphs/_head.html.haml4
-rw-r--r--app/views/projects/graphs/ci.html.haml13
-rw-r--r--app/views/projects/graphs/ci/_build_times.haml17
-rw-r--r--app/views/projects/graphs/ci/_builds.haml50
-rw-r--r--app/views/projects/graphs/ci/_overall.haml16
-rw-r--r--app/views/projects/graphs/commits.html.haml60
-rw-r--r--app/views/projects/graphs/show.html.haml29
-rw-r--r--app/views/projects/hooks/index.html.haml2
-rw-r--r--app/views/projects/imports/new.html.haml2
-rw-r--r--app/views/projects/issues/_closed_by_box.html.haml3
-rw-r--r--app/views/projects/issues/_discussion.html.haml6
-rw-r--r--app/views/projects/issues/_issues.html.haml7
-rw-r--r--app/views/projects/issues/show.html.haml3
-rw-r--r--app/views/projects/labels/destroy.js.haml2
-rw-r--r--app/views/projects/labels/index.html.haml6
-rw-r--r--app/views/projects/merge_requests/_discussion.html.haml2
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml8
-rw-r--r--app/views/projects/merge_requests/_merge_requests.html.haml6
-rw-r--r--app/views/projects/merge_requests/_new_compare.html.haml17
-rw-r--r--app/views/projects/merge_requests/_show.html.haml3
-rw-r--r--app/views/projects/merge_requests/show/_commits.html.haml4
-rw-r--r--app/views/projects/merge_requests/show/_diffs.html.haml2
-rw-r--r--app/views/projects/merge_requests/show/_how_to_merge.html.haml7
-rw-r--r--app/views/projects/merge_requests/widget/_heading.html.haml74
-rw-r--r--app/views/projects/merge_requests/widget/_merged.html.haml31
-rw-r--r--app/views/projects/merge_requests/widget/open/_accept.html.haml15
-rw-r--r--app/views/projects/merge_requests/widget/open/_check.html.haml8
-rw-r--r--app/views/projects/milestones/_form.html.haml6
-rw-r--r--app/views/projects/new.html.haml14
-rw-r--r--app/views/projects/notes/_note.html.haml2
-rw-r--r--app/views/projects/project_members/index.html.haml9
-rw-r--r--app/views/projects/protected_branches/_branches_list.html.haml59
-rw-r--r--app/views/projects/releases/edit.html.haml20
-rw-r--r--app/views/projects/remove_fork.js.haml2
-rw-r--r--app/views/projects/runners/edit.html.haml2
-rw-r--r--app/views/projects/runners/index.html.haml1
-rw-r--r--app/views/projects/runners/show.html.haml122
-rw-r--r--app/views/projects/services/index.html.haml39
-rw-r--r--app/views/projects/show.html.haml17
-rw-r--r--app/views/projects/snippets/_actions.html.haml11
-rw-r--r--app/views/projects/snippets/index.html.haml20
-rw-r--r--app/views/projects/snippets/show.html.haml46
-rw-r--r--app/views/projects/tags/_download.html.haml17
-rw-r--r--app/views/projects/tags/_tag.html.haml18
-rw-r--r--app/views/projects/tags/destroy.js.haml3
-rw-r--r--app/views/projects/tags/new.html.haml29
-rw-r--r--app/views/projects/tags/show.html.haml39
-rw-r--r--app/views/projects/tree/_blob_item.html.haml2
-rw-r--r--app/views/projects/tree/_readme.html.haml6
-rw-r--r--app/views/projects/tree/_tree_content.html.haml (renamed from app/views/projects/tree/_tree.html.haml)37
-rw-r--r--app/views/projects/tree/_tree_header.html.haml32
-rw-r--r--app/views/projects/tree/_tree_item.html.haml2
-rw-r--r--app/views/projects/tree/show.html.haml8
-rw-r--r--app/views/projects/triggers/index.html.haml14
-rw-r--r--app/views/projects/variables/show.html.haml1
-rw-r--r--app/views/projects/wikis/_form.html.haml4
-rw-r--r--app/views/projects/wikis/history.html.haml49
-rw-r--r--app/views/search/_category.html.haml7
-rw-r--r--app/views/search/results/_commit.html.haml2
-rw-r--r--app/views/shared/_clone_panel.html.haml4
-rw-r--r--app/views/shared/_logo.svg21
-rw-r--r--app/views/shared/issuable/_context.html.haml6
-rw-r--r--app/views/shared/issuable/_filter.html.haml21
-rw-r--r--app/views/shared/issuable/_form.html.haml9
-rw-r--r--app/views/shared/projects/_list.html.haml4
-rw-r--r--app/views/shared/projects/_project.html.haml4
-rw-r--r--app/views/shared/snippets/_header.html.haml24
-rw-r--r--app/views/shared/snippets/_snippet.html.haml1
-rw-r--r--app/views/sherlock/file_samples/show.html.haml55
-rw-r--r--app/views/sherlock/queries/_backtrace.html.haml27
-rw-r--r--app/views/sherlock/queries/_general.html.haml50
-rw-r--r--app/views/sherlock/queries/show.html.haml26
-rw-r--r--app/views/sherlock/transactions/_file_samples.html.haml24
-rw-r--r--app/views/sherlock/transactions/_general.html.haml33
-rw-r--r--app/views/sherlock/transactions/_queries.html.haml24
-rw-r--r--app/views/sherlock/transactions/index.html.haml42
-rw-r--r--app/views/sherlock/transactions/show.html.haml36
-rw-r--r--app/views/snippets/_actions.html.haml11
-rw-r--r--app/views/snippets/show.html.haml51
-rw-r--r--app/views/users/_projects.html.haml13
-rw-r--r--app/views/users/calendar.html.haml6
-rw-r--r--app/views/users/show.html.haml151
-rw-r--r--app/workers/repository_archive_cache_worker.rb9
-rw-r--r--app/workers/repository_archive_worker.rb43
-rw-r--r--app/workers/stuck_ci_builds_worker.rb18
392 files changed, 4401 insertions, 2653 deletions
diff --git a/app/assets/fonts/SourceSansPro-Black.ttf b/app/assets/fonts/SourceSansPro-Black.ttf
index cb89a2d171e..9c9b5cb7f03 100755..100644
--- a/app/assets/fonts/SourceSansPro-Black.ttf
+++ b/app/assets/fonts/SourceSansPro-Black.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-BlackIt.ttf b/app/assets/fonts/SourceSansPro-BlackIt.ttf
new file mode 100644
index 00000000000..294ce5abe8f
--- /dev/null
+++ b/app/assets/fonts/SourceSansPro-BlackIt.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-Bold.ttf b/app/assets/fonts/SourceSansPro-Bold.ttf
index 5d65c93242f..5d65c93242f 100755..100644
--- a/app/assets/fonts/SourceSansPro-Bold.ttf
+++ b/app/assets/fonts/SourceSansPro-Bold.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-BoldIt.ttf b/app/assets/fonts/SourceSansPro-BoldIt.ttf
new file mode 100644
index 00000000000..3decd130070
--- /dev/null
+++ b/app/assets/fonts/SourceSansPro-BoldIt.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-ExtraLight.ttf b/app/assets/fonts/SourceSansPro-ExtraLight.ttf
index bb4176c6fff..253eafa3783 100755..100644
--- a/app/assets/fonts/SourceSansPro-ExtraLight.ttf
+++ b/app/assets/fonts/SourceSansPro-ExtraLight.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf b/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf
new file mode 100644
index 00000000000..00d7e9a7aa8
--- /dev/null
+++ b/app/assets/fonts/SourceSansPro-ExtraLightIt.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-It.ttf b/app/assets/fonts/SourceSansPro-It.ttf
new file mode 100644
index 00000000000..f7af5377595
--- /dev/null
+++ b/app/assets/fonts/SourceSansPro-It.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-Light.ttf b/app/assets/fonts/SourceSansPro-Light.ttf
index 83a0a336661..83a0a336661 100755..100644
--- a/app/assets/fonts/SourceSansPro-Light.ttf
+++ b/app/assets/fonts/SourceSansPro-Light.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-LightIt.ttf b/app/assets/fonts/SourceSansPro-LightIt.ttf
new file mode 100644
index 00000000000..f18827985ef
--- /dev/null
+++ b/app/assets/fonts/SourceSansPro-LightIt.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-Regular.ttf b/app/assets/fonts/SourceSansPro-Regular.ttf
index 44486cdc670..44486cdc670 100755..100644
--- a/app/assets/fonts/SourceSansPro-Regular.ttf
+++ b/app/assets/fonts/SourceSansPro-Regular.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-Semibold.ttf b/app/assets/fonts/SourceSansPro-Semibold.ttf
index 86b00c067e0..86b00c067e0 100755..100644
--- a/app/assets/fonts/SourceSansPro-Semibold.ttf
+++ b/app/assets/fonts/SourceSansPro-Semibold.ttf
Binary files differ
diff --git a/app/assets/fonts/SourceSansPro-SemiboldIt.ttf b/app/assets/fonts/SourceSansPro-SemiboldIt.ttf
new file mode 100644
index 00000000000..13d66a1fc45
--- /dev/null
+++ b/app/assets/fonts/SourceSansPro-SemiboldIt.ttf
Binary files differ
diff --git a/app/assets/images/auth_buttons/facebook_64.png b/app/assets/images/auth_buttons/facebook_64.png
new file mode 100644
index 00000000000..1f1a80d7368
--- /dev/null
+++ b/app/assets/images/auth_buttons/facebook_64.png
Binary files differ
diff --git a/app/assets/images/logo.svg b/app/assets/images/logo.svg
index c09785cb96f..f4e19b67008 100644
--- a/app/assets/images/logo.svg
+++ b/app/assets/images/logo.svg
@@ -10,17 +10,17 @@
<g id="Fill-1-+-Group-24">
<g id="Group-24">
<g id="Group">
- <path d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" id="Fill-4" fill="#E24329"></path>
- <path d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-8" fill="#FC6D26"></path>
- <path d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" id="Fill-12" fill="#FCA326"></path>
- <path d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" id="Fill-16" fill="#E24329"></path>
- <path d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-18" fill="#FC6D26"></path>
- <path d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" id="Fill-20" fill="#FCA326"></path>
- <path d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" id="Fill-22" fill="#E24329"></path>
+ <path d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" id="Fill-4" fill="#E24329" class="tanuki-shape"></path>
+ <path d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-8" fill="#FC6D26" class="tanuki-shape"></path>
+ <path d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" id="Fill-12" fill="#FCA326" class="tanuki-shape"></path>
+ <path d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" id="Fill-16" fill="#E24329" class="tanuki-shape"></path>
+ <path d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-18" fill="#FC6D26" class="tanuki-shape"></path>
+ <path d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" id="Fill-20" fill="#FCA326" class="tanuki-shape"></path>
+ <path d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" id="Fill-22" fill="#E24329" class="tanuki-shape"></path>
</g>
</g>
</g>
</g>
</g>
</g>
-</svg> \ No newline at end of file
+</svg>
diff --git a/app/assets/javascripts/blob/edit_blob.js.coffee b/app/assets/javascripts/blob/edit_blob.js.coffee
index a6f65642d78..bf4cd85aee0 100644
--- a/app/assets/javascripts/blob/edit_blob.js.coffee
+++ b/app/assets/javascripts/blob/edit_blob.js.coffee
@@ -18,10 +18,10 @@ class @EditBlob
$('.form-group.destination').hide()
$('#create_merge_request').prop('checked', false)
- $(".js-commit-button").click ->
- $("#file-content").val editor.getValue()
- $(".file-editor form").submit()
- return false
+ # Before a form submission, move the content from the Ace editor into the
+ # submitted textarea
+ $('form').submit ->
+ $("#file-content").val(editor.getValue())
editModePanes = $(".js-edit-mode-pane")
editModeLinks = $(".js-edit-mode a")
diff --git a/app/assets/javascripts/blob/new_blob.js.coffee b/app/assets/javascripts/blob/new_blob.js.coffee
index f4e06ad088b..c2d6c7acfef 100644
--- a/app/assets/javascripts/blob/new_blob.js.coffee
+++ b/app/assets/javascripts/blob/new_blob.js.coffee
@@ -18,10 +18,10 @@ class @NewBlob
$('.form-group.destination').hide()
$('#create_merge_request').prop('checked', false)
- $(".js-commit-button").click ->
- $("#file-content").val editor.getValue()
- $(".file-editor form").submit()
- return false
+ # Before a form submission, move the content from the Ace editor into the
+ # submitted textarea
+ $('form').submit ->
+ $("#file-content").val(editor.getValue())
editor: ->
return @editor
diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee
index 4c4bc3d66ed..97621236924 100644
--- a/app/assets/javascripts/calendar.js.coffee
+++ b/app/assets/javascripts/calendar.js.coffee
@@ -25,7 +25,7 @@ class @Calendar
30
]
legendCellPadding: 3
- cellSize: $('.user-calendar').width() / 80
+ cellSize: $('.user-calendar').width() / 73
onClick: (date, count) ->
formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
$.ajax
diff --git a/app/assets/javascripts/ci/build.coffee b/app/assets/javascripts/ci/build.coffee
index c30859b484b..44d5ddb7d95 100644
--- a/app/assets/javascripts/ci/build.coffee
+++ b/app/assets/javascripts/ci/build.coffee
@@ -22,7 +22,7 @@ class CiBuild
# Only valid for runnig build when output changes during time
#
CiBuild.interval = setInterval =>
- if window.location.href is build_url
+ if window.location.href.split("#").first() is build_url
$.ajax
url: build_url
dataType: "json"
@@ -31,7 +31,7 @@ class CiBuild
$('#build-trace code').html build.trace_html
$('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>'
@checkAutoscroll()
- else
+ else if build.status != build_status
Turbolinks.visit build_url
, 4000
diff --git a/app/assets/javascripts/copy_to_clipboard.js.coffee b/app/assets/javascripts/copy_to_clipboard.js.coffee
new file mode 100644
index 00000000000..ec4b80cca6f
--- /dev/null
+++ b/app/assets/javascripts/copy_to_clipboard.js.coffee
@@ -0,0 +1,21 @@
+#= require clipboard
+
+$ ->
+ clipboard = new Clipboard '.js-clipboard-trigger',
+ text: (trigger) ->
+ $target = $(trigger.nextElementSibling || trigger.previousElementSibling)
+ $target.data('clipboard-text') || $target.text().trim()
+
+ clipboard.on 'success', (e) ->
+ $(e.trigger).
+ tooltip(trigger: 'manual', placement: 'auto bottom', title: 'Copied!').
+ tooltip('show')
+
+ # Clear the selection and blur the trigger so it loses its border
+ e.clearSelection()
+ $(e.trigger).blur()
+
+ # Manually hide the tooltip after 1 second
+ setTimeout(->
+ $(e.trigger).tooltip('hide')
+ , 1000)
diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee
index 5bf0b302179..4059fc39c67 100644
--- a/app/assets/javascripts/dispatcher.js.coffee
+++ b/app/assets/javascripts/dispatcher.js.coffee
@@ -28,6 +28,8 @@ class Dispatcher
when 'projects:milestones:new', 'projects:milestones:edit'
new ZenMode()
new DropzoneInput($('.milestone-form'))
+ when 'groups:milestones:new'
+ new ZenMode()
when 'projects:compare:show'
new Diff()
when 'projects:issues:new','projects:issues:edit'
@@ -39,6 +41,12 @@ class Dispatcher
shortcut_handler = new ShortcutsNavigation()
new DropzoneInput($('.merge-request-form'))
new IssuableForm($('.merge-request-form'))
+ when 'projects:tags:new'
+ new ZenMode()
+ new DropzoneInput($('.tag-form'))
+ when 'projects:releases:edit'
+ new ZenMode()
+ new DropzoneInput($('.release-form'))
when 'projects:merge_requests:show'
new Diff()
shortcut_handler = new ShortcutsIssuable()
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 6ce34b5c3e8..1635df9c97b 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -18,6 +18,7 @@
line-height: 36px;
}
+.content-block,
.gray-content-block {
margin: -$gl-padding;
background-color: $background-color;
@@ -27,6 +28,14 @@
border-bottom: 1px solid $border-color;
color: $gl-gray;
+ &.oneline-block {
+ line-height: 42px;
+ }
+
+ &.white {
+ background-color: white;
+ }
+
&.top-block {
border-top: none;
}
@@ -60,3 +69,48 @@
line-height: 42px;
}
}
+
+.cover-block {
+ text-align: center;
+ background: #f7f8fa;
+ margin: -$gl-padding;
+ margin-bottom: 0;
+ padding: 44px $gl-padding;
+ border-bottom: 1px solid $border-color;
+ position: relative;
+
+ .avatar-holder {
+ margin-bottom: 16px;
+
+ .avatar, .identicon {
+ margin: 0 auto;
+ float: none;
+ }
+
+ .identicon {
+ @include border-radius(50%);
+ }
+ }
+
+ .cover-title {
+ color: $gl-header-color;
+ margin: 0;
+ font-size: 23px;
+ font-weight: normal;
+ margin: 16px 0 5px 0;
+ color: #4c4e54;
+ font-size: 23px;
+ line-height: 1.1;
+ }
+
+ .cover-desc {
+ padding: 0 $gl-padding 3px;
+ color: $gl-text-color;
+ }
+
+ .cover-controls {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ }
+}
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index e5f0c0ad9ef..fe56266284b 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -162,10 +162,25 @@
border-color: #e7e9ed;
width: 140px;
+ .badge {
+ font-weight: normal;
+ background-color: #eee;
+ color: #78a;
+ }
+
&.active {
border-color: $gl-info;
background: $gl-info;
color: #fff;
+
+ .badge {
+ color: $gl-info;
+ background-color: white;
+ }
}
}
}
+
+.btn-clipboard {
+ border: none;
+}
diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss
index f1699d21c9b..f3ce4e3c219 100644
--- a/app/assets/stylesheets/framework/callout.scss
+++ b/app/assets/stylesheets/framework/callout.scss
@@ -9,9 +9,9 @@
.bs-callout {
margin: 20px 0;
padding: 20px;
- border-left: 3px solid #eee;
- color: #666;
- background: #f9f9f9;
+ border-left: 3px solid $border-color;
+ color: $text-color;
+ background: $background-color;
}
.bs-callout h4 {
margin-top: 0;
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index e1a1793be9c..ddbacd7fd41 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -16,6 +16,7 @@
.append-bottom-10 { margin-bottom:10px }
.append-bottom-15 { margin-bottom:15px }
.append-bottom-20 { margin-bottom:20px }
+.append-bottom-default { margin-bottom: $gl-padding; }
.inline { display: inline-block }
.center { text-align: center }
@@ -387,6 +388,36 @@ table {
}
}
+.center-middle-menu {
+ @include nav-menu;
+ padding: 0;
+ text-align: center;
+ margin: -$gl-padding;
+ margin-top: 0;
+ margin-bottom: 0;
+ height: 58px;
+ border-bottom: 1px solid $border-color;
+
+ li {
+ &:after {
+ content: "|";
+ color: $border-gray-light;
+ }
+
+ &:last-child {
+ &:after {
+ content: none;
+ }
+ }
+
+ > a {
+ display: inline-block;
+ text-transform: uppercase;
+ font-size: 13px;
+ }
+ }
+}
+
.dropzone .dz-preview .dz-progress {
border-color: $border-color !important;
}
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 9dd77747884..35db00281e5 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -10,6 +10,10 @@
border-bottom: 1px solid #E7E9EE;
margin-bottom: 1em;
+ &.readme-holder {
+ border-bottom: 0;
+ }
+
table {
@extend .table;
}
@@ -94,7 +98,6 @@
border-right: none;
}
background: #fff;
- padding: 10px $gl-padding;
}
.lines {
pre {
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 91e6975e269..02ea91602e8 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -118,6 +118,10 @@ header {
}
}
}
+
+ .impersonation i {
+ color: $red-normal;
+ }
}
@mixin collapsed-header {
diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss
index c7b3b60e769..b91c15d8910 100644
--- a/app/assets/stylesheets/framework/layout.scss
+++ b/app/assets/stylesheets/framework/layout.scss
@@ -5,7 +5,6 @@ html {
body {
padding-top: $header-height;
- text-rendering: geometricPrecision;
}
}
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index c5764c36597..45f3b5849bf 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -107,7 +107,7 @@ ul.content-list {
> li {
padding: $gl-padding;
- border-color: #f1f2f4;
+ border-color: $table-border-color;
margin-left: -$gl-padding;
margin-right: -$gl-padding;
color: $gl-gray;
@@ -117,7 +117,7 @@ ul.content-list {
}
.controls {
- padding-top: 4px;
+ padding-top: 1px;
float: right;
.btn {
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index ed0333d2336..cc660529cb4 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -106,6 +106,7 @@
}
.markdown-area {
+ @include border-radius(0);
background: #FFF;
border: 1px solid #ddd;
min-height: 140px;
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 089e6958eeb..11c48d26ab5 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -72,9 +72,10 @@
list-style: none;
> li {
+ @include clearfix;
+
padding: 10px 0;
border-bottom: 1px solid #EEE;
- overflow: hidden;
display: block;
margin: 0px;
@@ -137,6 +138,7 @@
&:hover, &:active, &:focus {
text-decoration: none;
+ outline: none;
}
}
@@ -147,14 +149,8 @@
.badge {
font-weight: normal;
- background-color: #fff;
background-color: #eee;
color: #78a;
}
}
}
-
-.fa-align {
- top: 20px;
- position: relative;
-}
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index cba621635b6..78fff58d232 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -32,7 +32,7 @@
}
.select2-results .select2-result-label {
- padding: 16px;
+ padding: 9px;
}
.select2-drop{
@@ -143,4 +143,4 @@
.ajax-users-dropdown {
min-width: 250px !important;
-}
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index c5ea3aca7ca..c1b0129c866 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -64,6 +64,7 @@
text-decoration: none;
padding-left: 22px;
font-weight: normal;
+ outline: none;
&:hover {
text-decoration: none;
@@ -176,6 +177,7 @@
text-align: center;
line-height: 40px;
transition-duration: .3s;
+ outline: none;
}
.collapse-nav a:hover {
@@ -238,10 +240,14 @@
width: 100%;
padding: 10px 22px;
overflow: hidden;
+ outline: none;
img {
width: 36px;
height: 36px;
+ }
+
+ #tanuki-logo, img {
float: left;
}
@@ -265,3 +271,13 @@
}
}
}
+
+
+.tanuki-shape {
+ transition: all 0.8s;
+
+ &:hover {
+ fill: rgb(255, 255, 255);
+ transition: all 0.1s;
+ }
+}
diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index 789b34020c1..66e16e8df75 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -1,3 +1,9 @@
+.table-holder {
+ margin: -$gl-padding;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
table {
&.table {
.dropdown-menu a {
@@ -18,15 +24,17 @@ table {
tr {
td, th {
- padding: 8px 10px;
+ padding: 10px $gl-padding;
line-height: 20px;
vertical-align: middle;
}
+
th {
font-weight: normal;
font-size: 15px;
border-bottom: 1px solid $border-color !important;
}
+
td {
border-color: $table-border-color !important;
border-bottom: 1px solid;
diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss
index bf21d7fce76..eb53c4153d3 100644
--- a/app/assets/stylesheets/framework/timeline.scss
+++ b/app/assets/stylesheets/framework/timeline.scss
@@ -6,13 +6,17 @@
.timeline-entry {
padding: $gl-padding;
- border-color: #f1f2f4;
+ border-color: $table-border-color;
margin-left: -$gl-padding;
margin-right: -$gl-padding;
color: $gl-gray;
border-bottom: 1px solid #ECEEF1;
border-right: 1px solid #ECEEF1;
+ &:target {
+ background: $hover;
+ }
+
&:last-child {
border-bottom: none;
}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 6ccc084526a..ba0312ba0db 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -1,5 +1,6 @@
@mixin md-typography {
color: $md-text-color;
+ word-wrap: break-word;
a {
color: $md-link-color;
@@ -17,7 +18,6 @@
font-family: $monospace_font;
white-space: pre;
word-wrap: normal;
- padding: 1px 2px;
}
kbd {
@@ -73,6 +73,8 @@
}
blockquote {
+ color: #7f8fa4;
+ font-size: inherit;
padding: 8px 21px;
margin: 12px 0 12px;
border-left: 3px solid #e7e9ed;
@@ -80,7 +82,7 @@
blockquote p {
color: #7f8fa4 !important;
- font-size: 15px;
+ font-size: inherit;
line-height: 1.5;
}
@@ -112,9 +114,9 @@
font-weight: inherit;
}
-
- ul {
- color: #5c5d5e;
+ ul, ol {
+ padding: 0;
+ margin: 6px 0 6px 18px !important;
}
li {
@@ -136,6 +138,33 @@
text-decoration: none;
}
}
+
+ /* Link to current header. */
+ h1, h2, h3, h4, h5, h6 {
+ position: relative;
+
+ a.anchor {
+ // Setting `display: none` would prevent the anchor being scrolled to, so
+ // instead we set the height to 0 and it gets updated on hover.
+ height: 0;
+ }
+
+ &:hover > a.anchor {
+ $size: 16px;
+ position: absolute;
+ right: 100%;
+ top: 50%;
+ margin-top: -$size/2;
+ margin-right: 0px;
+ padding-right: 20px;
+ display: inline-block;
+ width: $size;
+ height: $size;
+ background-image: image-url("icon-link.png");
+ background-size: contain;
+ background-repeat: no-repeat;
+ }
+ }
}
@@ -144,7 +173,6 @@
*
*/
body {
- text-rendering:optimizeLegibility;
-webkit-text-shadow: rgba(255,255,255,0.01) 0 0 1px;
}
@@ -202,53 +230,11 @@ a > code {
}
/**
- * Wiki typography
+ * Apply Markdown typography
*
*/
.wiki {
@include md-typography;
-
- word-wrap: break-word;
- padding: 7px;
-
- /* Link to current header. */
- h1, h2, h3, h4, h5, h6 {
- position: relative;
-
- a.anchor {
- // Setting `display: none` would prevent the anchor being scrolled to, so
- // instead we set the height to 0 and it gets updated on hover.
- height: 0;
- }
-
- &:hover > a.anchor {
- $size: 16px;
- position: absolute;
- right: 100%;
- top: 50%;
- margin-top: -$size/2;
- margin-right: 0px;
- padding-right: 20px;
- display: inline-block;
- width: $size;
- height: $size;
- background-image: image-url("icon-link.png");
- background-size: contain;
- background-repeat: no-repeat;
- }
- }
-
- ul,ol {
- padding: 0;
- margin: 6px 0 6px 18px !important;
- }
- ol {
- color: #5c5d5e;
- }
-}
-
-.md-area {
- @include md-typography;
}
.md {
@@ -261,6 +247,7 @@ a > code {
*/
textarea.js-gfm-input {
font-family: $monospace_font;
+ color: $gl-text-color;
}
.md-preview {
diff --git a/app/assets/stylesheets/pages/ci_projects.scss b/app/assets/stylesheets/pages/ci_projects.scss
index 8c5273abcda..2a7b5cfc7fd 100644
--- a/app/assets/stylesheets/pages/ci_projects.scss
+++ b/app/assets/stylesheets/pages/ci_projects.scss
@@ -6,11 +6,6 @@
line-height: 1.5;
}
- .wide-table-holder {
- margin-left: -$gl-padding;
- margin-right: -$gl-padding;
- }
-
.builds,
.projects-table {
.light {
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 4e121b95d13..c9dfcff6290 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -33,6 +33,8 @@
}
li.commit {
+ list-style: none;
+
.commit-row-title {
font-size: $list-font-size;
line-height: 20px;
@@ -113,3 +115,10 @@ li.commit {
}
}
}
+
+.branch-commit {
+ color: $gl-gray;
+ .commit-id, .commit-row-message {
+ color: $gl-gray;
+ }
+}
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index d9ef06dc6b6..afd6fb73675 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -367,7 +367,6 @@
.inline-parallel-buttons {
float: right;
- margin-top: -5px;
}
// Mobile
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 6bc9b1c3eaf..c0defa82bff 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -50,7 +50,7 @@
.editor-file-name {
.new-file-name {
display: inline-block;
- width: 200px;
+ width: 450px;
}
.form-control {
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index ca2ee455423..282aaf2219b 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -4,10 +4,10 @@
*/
.event-item {
font-size: $gl-font-size;
- padding: $gl-padding;
+ padding: $gl-padding $gl-padding $gl-padding ($gl-padding + $gl-avatar-size + 15px);
margin-left: -$gl-padding;
margin-right: -$gl-padding;
- border-bottom: 1px solid #f1f2f4;
+ border-bottom: 1px solid $table-border-color;
color: #7f8fa4;
&.event-inline {
@@ -16,10 +16,7 @@
top: -2px;
}
- .event-title {
- line-height: 44px;
- }
-
+ .event-title,
.event-item-timestamp {
line-height: 44px;
}
@@ -30,7 +27,7 @@
}
.avatar {
- margin-right: 15px;
+ margin-left: -($gl-avatar-size + 15px);
}
.event-title {
@@ -43,8 +40,7 @@
}
.event-body {
- margin-left: 63px;
- margin-right: 80px;
+ margin-right: 174px;
.event-note {
margin-top: 5px;
@@ -155,6 +151,8 @@
@media (max-width: $screen-xs-max) {
.event-item {
+ padding-left: $gl-padding;
+
.event-title {
white-space: normal;
overflow: visible;
diff --git a/app/assets/stylesheets/pages/help.scss b/app/assets/stylesheets/pages/help.scss
index 6da7a2511a2..bd224705f04 100644
--- a/app/assets/stylesheets/pages/help.scss
+++ b/app/assets/stylesheets/pages/help.scss
@@ -68,3 +68,7 @@ body.modal-open {
.modal .modal-dialog {
width: 860px;
}
+
+.documentation {
+ padding: 7px;
+}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 9da085a3473..abc27a19e32 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -80,3 +80,24 @@
}
}
}
+
+.issuable-filter-count {
+ span {
+ display: block;
+ margin-bottom: -16px;
+ padding: 13px 0;
+ }
+}
+
+.cross-project-reference {
+ text-align: center;
+ width: 100%;
+
+ .slead {
+ padding: 5px;
+ }
+
+ span, button {
+ background-color: $background-color;
+ }
+}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 4bf58cb4a59..41c069f0ad3 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -132,6 +132,11 @@ form.edit-issue {
}
}
+.issue-closed-by-widget {
+ padding: 16px 0;
+ margin: 0px;
+}
+
.issue-form .select2-container {
width: 250px !important;
}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index a1a5208c59c..08e4bcdf529 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -19,6 +19,20 @@
.accept-merge-holder {
.accept-action {
display: inline-block;
+
+ .accept_merge_request {
+ &.ci-pending,
+ &.ci-running {
+ @include btn-orange;
+ }
+
+ &.ci-skipped,
+ &.ci-failed,
+ &.ci-canceled,
+ &.ci-error {
+ @include btn-red;
+ }
+ }
}
.accept-control {
@@ -205,6 +219,15 @@
#modal_merge_info .modal-dialog {
width: 600px;
+
+ .btn-clipboard {
+ @extend .pull-right;
+
+ margin-right: 18px;
+ margin-top: 5px;
+ position: absolute;
+ right: 0;
+ }
}
.mr-source-target {
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 4392f08942b..268fc995aa7 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -56,6 +56,10 @@
.note_text {
width: 100%;
}
+
+ .comment-hints {
+ margin-top: -12px;
+ }
}
/* loading indicator */
@@ -168,7 +172,7 @@
color: #999;
background: #FFF;
padding: 7px;
- margin-top: -11px;
+ margin-top: -7px;
border: 1px solid $border-color;
font-size: 13px;
}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index abb03b07f51..1980fe0d458 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -30,7 +30,6 @@ ul.notes {
.discussion-header,
.note-header {
@extend .cgray;
- padding-bottom: 15px;
a:hover {
text-decoration: none;
@@ -75,6 +74,10 @@ ul.notes {
}
}
+ .discussion-body {
+ padding-top: 15px;
+ }
+
.discussion {
overflow: hidden;
display: block;
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 8e4f0eb2b25..1d6ca0dfc13 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -47,3 +47,31 @@
}
}
}
+
+.calendar-hint {
+ margin-top: -12px;
+ float: right;
+ font-size: 12px;
+}
+
+.profile-link-holder {
+ display: inline;
+
+ &:after {
+ content: "\00B7";
+ padding: 0px 6px;
+ font-weight: bold;
+ }
+
+ &:last-child {
+ &:after {
+ content: "";
+ padding: 0;
+ }
+ }
+
+ a {
+ color: $blue-dark;
+ text-decoration: none;
+ }
+}
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index f7a22849003..d3b10040022 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -50,7 +50,17 @@
}
.project-home-dropdown {
- margin: 11px 3px 0;
+ margin: 13px 0px 0;
+ }
+
+ .notifications-btn {
+ .fa-bell {
+ margin-right: 6px;
+ }
+
+ .fa-angle-down {
+ margin-left: 6px;
+ }
}
.project-home-desc {
@@ -85,6 +95,7 @@
color: inherit;
}
}
+
.input-group {
display: inline-table;
position: relative;
@@ -233,23 +244,11 @@
}
}
- .fa-fw {
+ i {
margin-right: 8px;
}
}
-.fa-bell {
- margin-right: 6px;
-}
-
-.fa-angle-down {
- margin-left: 6px;
-}
-
-.project-home-panel .project-home-dropdown {
- margin: 13px 0px 0;
-}
-
.project-visibility-level-holder {
.radio {
margin-bottom: 10px;
@@ -457,7 +456,7 @@ pre.light-well {
.project-row {
padding: $gl-padding;
- border-color: #f1f2f4;
+ border-color: $table-border-color;
margin-left: -$gl-padding;
margin-right: -$gl-padding;
@@ -511,3 +510,46 @@ pre.light-well {
margin-top: -1px;
}
}
+
+.project-last-commit {
+ margin: 0 7px;
+
+ .ci-status {
+ margin-right: 16px;
+ }
+
+ .commit-row-message {
+ color: $gl-gray;
+ }
+
+ .commit_short_id {
+ margin-right: 5px;
+ color: $gl-link-color;
+ font-weight: 600;
+ }
+
+ .commit-author-link {
+ margin-left: 7px;
+ text-decoration: none;
+ .avatar {
+ float: none;
+ margin-right: 4px;
+ }
+
+ .commit-author-name {
+ font-weight: 600;
+ }
+ }
+}
+
+.project-show-readme .readme-holder {
+ margin-left: -$gl-padding;
+ margin-right: -$gl-padding;
+ padding: ($gl-padding + 7px);
+ border-top: 0;
+
+ .edit-project-readme {
+ z-index: 100;
+ position: relative;
+ }
+} \ No newline at end of file
diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss
index 2b15ab83129..a9111a7388f 100644
--- a/app/assets/stylesheets/pages/runners.scss
+++ b/app/assets/stylesheets/pages/runners.scss
@@ -1,36 +1,34 @@
-.ci-body {
- .runner-state {
- padding: 6px 12px;
- margin-right: 10px;
- color: #FFF;
+.runner-state {
+ padding: 6px 12px;
+ margin-right: 10px;
+ color: #FFF;
- &.runner-state-shared {
- background: #32b186;
- }
- &.runner-state-specific {
- background: #3498db;
- }
+ &.runner-state-shared {
+ background: #32b186;
}
-
- .runner-status-online {
- color: green;
+ &.runner-state-specific {
+ background: #3498db;
}
+}
- .runner-status-offline {
- color: gray;
- }
+.runner-status-online {
+ color: green;
+}
- .runner-status-paused {
- color: red;
- }
+.runner-status-offline {
+ color: gray;
+}
+
+.runner-status-paused {
+ color: red;
+}
- .runner {
- .btn {
- padding: 1px 6px;
- }
+.runner {
+ .btn {
+ padding: 1px 6px;
+ }
- h4 {
- font-weight: normal;
- }
+ h4 {
+ font-weight: normal;
}
}
diff --git a/app/assets/stylesheets/pages/sherlock.scss b/app/assets/stylesheets/pages/sherlock.scss
new file mode 100644
index 00000000000..92d84d9640f
--- /dev/null
+++ b/app/assets/stylesheets/pages/sherlock.scss
@@ -0,0 +1,33 @@
+table .sherlock-code {
+ max-width: 700px;
+}
+
+.sherlock-code {
+ pre {
+ word-wrap: normal;
+ }
+
+ pre code {
+ white-space: pre;
+ }
+}
+
+.sherlock-line-samples-table {
+ margin-bottom: 0px !important;
+
+ thead tr th,
+ tbody tr td {
+ font-size: 13px !important;
+ text-align: right;
+ padding: 0px 10px !important;
+ }
+}
+
+.sherlock-file-sample pre {
+ padding-top: 28px !important;
+}
+
+.sherlock-line-samples-table .slow {
+ color: $red-light;
+ font-weight: bold;
+}
diff --git a/app/assets/stylesheets/pages/snippets.scss b/app/assets/stylesheets/pages/snippets.scss
index a3d7aba054d..242783a7b7e 100644
--- a/app/assets/stylesheets/pages/snippets.scss
+++ b/app/assets/stylesheets/pages/snippets.scss
@@ -1,8 +1,3 @@
-.my-snippets li:first-child {
- h4 { margin-top: 0; }
- padding-top: 0;
-}
-
.snippet-form-holder .file-holder .file-title {
padding: 2px;
}
@@ -30,3 +25,58 @@
}
}
}
+
+.snippet-holder {
+ .snippet-details {
+ .page-title {
+ margin-top: -15px;
+ padding: 10px 0;
+ margin-bottom: 0;
+ color: #5c5d5e;
+ font-size: 16px;
+
+ .author {
+ color: #5c5d5e;
+ }
+
+ .snippet-id {
+ color: #5c5d5e;
+ }
+ }
+
+ .snippet-title {
+ margin: 0;
+ font-size: 23px;
+ color: #313236;
+ }
+
+ @media (max-width: $screen-md-max) {
+ .new-snippet-link {
+ display: none;
+ }
+ }
+
+ @media (max-width: $screen-sm-max) {
+ .creator,
+ .page-title .btn-close {
+ display: none;
+ }
+ }
+ }
+
+ .file-holder {
+ border-top: 0;
+ }
+}
+
+
+.snippet-box {
+ @include border-radius(2px);
+
+ display: inline-block;
+ padding: 10px $gl-padding;
+ font-weight: normal;
+ margin-right: 10px;
+ font-size: $gl-font-size;
+ border: 1px solid;
+}
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index dadd86e88cc..d4ab6967ccd 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -1,25 +1,11 @@
.tree-holder {
- .tree-table-holder {
- margin-left: -$gl-padding;
- margin-right: -$gl-padding;
- }
-
- .tree_progress {
- display: none;
- margin: 20px;
- &.loading {
- display: block;
- }
- }
.tree-table {
margin-bottom: 0;
tr {
> td, > th {
- padding: 10px $gl-padding;
- line-height: 32px;
- border-color: $table-border-color !important;
+ line-height: 28px;
}
&:hover {
diff --git a/app/controllers/abuse_reports_controller.rb b/app/controllers/abuse_reports_controller.rb
index 65dbd5ef551..2f4054eaa11 100644
--- a/app/controllers/abuse_reports_controller.rb
+++ b/app/controllers/abuse_reports_controller.rb
@@ -9,6 +9,10 @@ class AbuseReportsController < ApplicationController
@abuse_report.reporter = current_user
if @abuse_report.save
+ if current_application_settings.admin_notification_email.present?
+ AbuseReportMailer.delay.notify(@abuse_report.id)
+ end
+
message = "Thank you for your report. A GitLab administrator will look into it shortly."
redirect_to root_path, notice: message
else
diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb
index 56e24386463..9083bfb41cf 100644
--- a/app/controllers/admin/application_controller.rb
+++ b/app/controllers/admin/application_controller.rb
@@ -8,4 +8,10 @@ class Admin::ApplicationController < ApplicationController
def authenticate_admin!
return render_404 unless current_user.is_admin?
end
+
+ def authorize_impersonator!
+ if session[:impersonator_id]
+ User.find_by!(username: session[:impersonator_id]).admin?
+ end
+ end
end
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 7c134d2ec9b..a9bcfc7456a 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -55,7 +55,10 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:default_snippet_visibility,
:restricted_signup_domains_raw,
:version_check_enabled,
+ :admin_notification_email,
:user_oauth_applications,
+ :shared_runners_enabled,
+ :max_artifacts_size,
restricted_visibility_levels: [],
import_sources: []
)
diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb
index 0808024fc39..497c34f8f49 100644
--- a/app/controllers/admin/broadcast_messages_controller.rb
+++ b/app/controllers/admin/broadcast_messages_controller.rb
@@ -19,7 +19,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
BroadcastMessage.find(params[:id]).destroy
respond_to do |format|
- format.html { redirect_to :back }
+ format.html { redirect_back_or_default(default: { action: 'index' }) }
format.js { render nothing: true }
end
end
diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb
index d670386f8c6..0bd19c49d8f 100644
--- a/app/controllers/admin/hooks_controller.rb
+++ b/app/controllers/admin/hooks_controller.rb
@@ -35,7 +35,7 @@ class Admin::HooksController < Admin::ApplicationController
}
@hook.execute(data, 'system_hooks')
- redirect_to :back
+ redirect_back_or_default
end
def hook_params
diff --git a/app/controllers/admin/impersonation_controller.rb b/app/controllers/admin/impersonation_controller.rb
new file mode 100644
index 00000000000..0382402afa6
--- /dev/null
+++ b/app/controllers/admin/impersonation_controller.rb
@@ -0,0 +1,32 @@
+class Admin::ImpersonationController < Admin::ApplicationController
+ skip_before_action :authenticate_admin!, only: :destroy
+
+ before_action :user
+ before_action :authorize_impersonator!
+
+ def create
+ session[:impersonator_id] = current_user.username
+ session[:impersonator_return_to] = request.env['HTTP_REFERER']
+
+ warden.set_user(user, scope: 'user')
+
+ flash[:alert] = "You are impersonating #{user.username}."
+
+ redirect_to root_path
+ end
+
+ def destroy
+ redirect = session[:impersonator_return_to]
+
+ warden.set_user(user, scope: 'user')
+
+ session[:impersonator_return_to] = nil
+ session[:impersonator_id] = nil
+
+ redirect_to redirect || root_path
+ end
+
+ def user
+ @user ||= User.find_by!(username: params[:id] || session[:impersonator_id])
+ end
+end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 00f41a10dd1..d7c927d444c 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -33,42 +33,36 @@ class Admin::UsersController < Admin::ApplicationController
def block
if user.block
- redirect_to :back, notice: "Successfully blocked"
+ redirect_back_or_admin_user(notice: "Successfully blocked")
else
- redirect_to :back, alert: "Error occurred. User was not blocked"
+ redirect_back_or_admin_user(alert: "Error occurred. User was not blocked")
end
end
def unblock
if user.activate
- redirect_to :back, notice: "Successfully unblocked"
+ redirect_back_or_admin_user(notice: "Successfully unblocked")
else
- redirect_to :back, alert: "Error occurred. User was not unblocked"
+ redirect_back_or_admin_user(alert: "Error occurred. User was not unblocked")
end
end
def unlock
if user.unlock_access!
- redirect_to :back, alert: "Successfully unlocked"
+ redirect_back_or_admin_user(alert: "Successfully unlocked")
else
- redirect_to :back, alert: "Error occurred. User was not unlocked"
+ redirect_back_or_admin_user(alert: "Error occurred. User was not unlocked")
end
end
def confirm
if user.confirm
- redirect_to :back, notice: "Successfully confirmed"
+ redirect_back_or_admin_user(notice: "Successfully confirmed")
else
- redirect_to :back, alert: "Error occurred. User was not confirmed"
+ redirect_back_or_admin_user(alert: "Error occurred. User was not confirmed")
end
end
- def login_as
- sign_in(user)
- flash[:alert] = "Logged in as #{user.username}"
- redirect_to root_path
- end
-
def disable_two_factor
user.disable_two_factor!
redirect_to admin_user_path(user),
@@ -138,7 +132,7 @@ class Admin::UsersController < Admin::ApplicationController
user.update_secondary_emails!
respond_to do |format|
- format.html { redirect_to :back, notice: "Successfully removed email." }
+ format.html { redirect_back_or_admin_user(notice: "Successfully removed email.") }
format.js { render nothing: true }
end
end
@@ -157,4 +151,12 @@ class Admin::UsersController < Admin::ApplicationController
:projects_limit, :can_create_group, :admin, :key_id
)
end
+
+ def redirect_back_or_admin_user(options = {})
+ redirect_back_or_default(default: default_route, options: options)
+ end
+
+ def default_route
+ [:admin, @user]
+ end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 258e37e98c0..6f87ee08b2d 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -34,6 +34,10 @@ class ApplicationController < ActionController::Base
render_404
end
+ def redirect_back_or_default(default: root_path, options: {})
+ redirect_to request.referer.present? ? :back : default, options
+ end
+
protected
# From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example
@@ -56,13 +60,8 @@ class ApplicationController < ActionController::Base
end
def authenticate_user!(*args)
- # If user is not signed-in and tries to access root_path - redirect him to landing page
- # Don't redirect to the default URL to prevent endless redirections
- if current_application_settings.home_page_url.present? &&
- current_application_settings.home_page_url.chomp('/') != Gitlab.config.gitlab['url'].chomp('/')
- if current_user.nil? && root_path == request.path
- redirect_to current_application_settings.home_page_url and return
- end
+ if redirect_to_home_page_url?
+ redirect_to current_application_settings.home_page_url and return
end
super(*args)
@@ -121,7 +120,6 @@ class ApplicationController < ActionController::Base
project_path = "#{namespace}/#{id}"
@project = Project.find_with_namespace(project_path)
-
if @project and can?(current_user, :read_project, @project)
if @project.path_with_namespace != project_path
redirect_to request.original_url.gsub(project_path, @project.path_with_namespace) and return
@@ -373,4 +371,17 @@ class ApplicationController < ActionController::Base
}
}
end
+
+ def redirect_to_home_page_url?
+ # If user is not signed-in and tries to access root_path - redirect him to landing page
+ # Don't redirect to the default URL to prevent endless redirections
+ return false unless current_application_settings.home_page_url.present?
+
+ home_page_url = current_application_settings.home_page_url.chomp('/')
+ root_urls = [Gitlab.config.gitlab['url'].chomp('/'), root_url.chomp('/')]
+
+ return false if root_urls.include?(home_page_url)
+
+ current_user.nil? && root_path == request.path
+ end
end
diff --git a/app/controllers/ci/admin/runners_controller.rb b/app/controllers/ci/admin/runners_controller.rb
index 110954a612d..0cafad27418 100644
--- a/app/controllers/ci/admin/runners_controller.rb
+++ b/app/controllers/ci/admin/runners_controller.rb
@@ -17,6 +17,7 @@ module Ci
@projects = @projects.where(gitlab_id: @gl_projects.select(:id))
end
@projects = @projects.where("ci_projects.id NOT IN (?)", @runner.projects.pluck(:id)) if @runner.projects.any?
+ @projects = @projects.joins(:gl_project)
@projects = @projects.page(params[:page]).per(30)
end
diff --git a/app/controllers/ci/application_controller.rb b/app/controllers/ci/application_controller.rb
index 9be470660e6..848f2b4e314 100644
--- a/app/controllers/ci/application_controller.rb
+++ b/app/controllers/ci/application_controller.rb
@@ -8,14 +8,6 @@ module Ci
private
- def authenticate_public_page!
- unless project.public
- authenticate_user!
-
- return access_denied! unless can?(current_user, :read_project, gl_project)
- end
- end
-
def authenticate_token!
unless project.valid_token?(params[:token])
return head(403)
diff --git a/app/controllers/ci/events_controller.rb b/app/controllers/ci/events_controller.rb
deleted file mode 100644
index 89b784a1e89..00000000000
--- a/app/controllers/ci/events_controller.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-module Ci
- class EventsController < Ci::ApplicationController
- EVENTS_PER_PAGE = 50
-
- before_action :authenticate_user!
- before_action :project
- before_action :authorize_manage_project!
-
- layout 'ci/project'
-
- def index
- @events = project.events.order("created_at DESC").page(params[:page]).per(EVENTS_PER_PAGE)
- end
-
- private
-
- def project
- @project ||= Ci::Project.find(params[:project_id])
- end
- end
-end
diff --git a/app/controllers/ci/projects_controller.rb b/app/controllers/ci/projects_controller.rb
index 7777aa18031..8406399fb60 100644
--- a/app/controllers/ci/projects_controller.rb
+++ b/app/controllers/ci/projects_controller.rb
@@ -1,12 +1,17 @@
module Ci
class ProjectsController < Ci::ApplicationController
- before_action :project
- before_action :authenticate_user!, except: [:build, :badge]
- before_action :authorize_access_project!, except: [:badge]
+ before_action :project, except: [:index]
+ before_action :authenticate_user!, except: [:index, :build, :badge]
+ before_action :authorize_access_project!, except: [:index, :badge]
before_action :authorize_manage_project!, only: [:toggle_shared_runners, :dumped_yaml]
before_action :no_cache, only: [:badge]
protect_from_forgery
+ def show
+ # Temporary compatibility with CI badges pointing to CI project page
+ redirect_to namespace_project_path(project.gl_project.namespace, project.gl_project)
+ end
+
# Project status badge
# Image with build status for sha or ref
def badge
@@ -21,10 +26,6 @@ module Ci
redirect_to namespace_project_runners_path(project.gl_project.namespace, project.gl_project)
end
- def dumped_yaml
- send_data @project.generated_yaml_config, filename: '.gitlab-ci.yml'
- end
-
protected
def project
diff --git a/app/controllers/ci/runner_projects_controller.rb b/app/controllers/ci/runner_projects_controller.rb
index 97f01d40af5..9d555313369 100644
--- a/app/controllers/ci/runner_projects_controller.rb
+++ b/app/controllers/ci/runner_projects_controller.rb
@@ -4,8 +4,6 @@ module Ci
before_action :project
before_action :authorize_manage_project!
- layout 'ci/project'
-
def create
@runner = Ci::Runner.find(params[:runner_project][:runner_id])
diff --git a/app/controllers/concerns/global_milestones.rb b/app/controllers/concerns/global_milestones.rb
new file mode 100644
index 00000000000..b428249acd3
--- /dev/null
+++ b/app/controllers/concerns/global_milestones.rb
@@ -0,0 +1,19 @@
+module GlobalMilestones
+ extend ActiveSupport::Concern
+
+ def milestones
+ @milestones = MilestonesFinder.new.execute(@projects, params)
+ @milestones = GlobalMilestone.build_collection(@milestones)
+ @milestones = Kaminari.paginate_array(@milestones).page(params[:page]).per(ApplicationController::PER_PAGE)
+ end
+
+ def milestone
+ milestones = Milestone.of_projects(@projects).where(title: params[:title])
+
+ if milestones.present?
+ @milestone = GlobalMilestone.new(params[:title], milestones)
+ else
+ render_404
+ end
+ end
+end
diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb
index 53896d4f2c7..2bdce0f8a00 100644
--- a/app/controllers/dashboard/milestones_controller.rb
+++ b/app/controllers/dashboard/milestones_controller.rb
@@ -1,34 +1,19 @@
class Dashboard::MilestonesController < Dashboard::ApplicationController
- before_action :load_projects
+ include GlobalMilestones
+
+ before_action :projects
+ before_action :milestones, only: [:index]
+ before_action :milestone, only: [:show]
def index
- project_milestones = case params[:state]
- when 'all'; state
- when 'closed'; state('closed')
- else state('active')
- end
- @dashboard_milestones = Milestones::GroupService.new(project_milestones).execute
- @dashboard_milestones = Kaminari.paginate_array(@dashboard_milestones).page(params[:page]).per(PER_PAGE)
end
def show
- project_milestones = Milestone.where(project_id: @projects).order("due_date ASC")
- @dashboard_milestone = Milestones::GroupService.new(project_milestones).milestone(title)
end
private
- def load_projects
- @projects = current_user.authorized_projects.sorted_by_activity.non_archived
- end
-
- def title
- params[:title]
- end
-
- def state(state = nil)
- conditions = { project_id: @projects }
- conditions.reverse_merge!(state: state) if state
- Milestone.where(conditions).order("title ASC")
+ def projects
+ @projects ||= current_user.authorized_projects.sorted_by_activity.non_archived
end
end
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 4ebb3d7276e..b2c1fa4230c 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -1,5 +1,6 @@
class DashboardController < Dashboard::ApplicationController
before_action :event_filter, only: :activity
+ before_action :projects, only: [:issues, :merge_requests]
respond_to :html
@@ -47,4 +48,8 @@ class DashboardController < Dashboard::ApplicationController
@events = @event_filter.apply_filter(@events).with_associations
@events = @events.limit(20).offset(params[:offset] || 0)
end
+
+ def projects
+ @projects ||= current_user.authorized_projects.sorted_by_activity.non_archived
+ end
end
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
index 6878d4bc07e..be801858eaf 100644
--- a/app/controllers/groups/application_controller.rb
+++ b/app/controllers/groups/application_controller.rb
@@ -1,8 +1,13 @@
class Groups::ApplicationController < ApplicationController
layout 'group'
+ before_action :group
private
-
+
+ def group
+ @group ||= Group.find_by(path: params[:group_id])
+ end
+
def authorize_read_group!
unless @group and can?(current_user, :read_group, @group)
if current_user.nil?
@@ -12,13 +17,13 @@ class Groups::ApplicationController < ApplicationController
end
end
end
-
+
def authorize_admin_group!
unless can?(current_user, :admin_group, group)
return render_404
end
end
-
+
def authorize_admin_group_member!
unless can?(current_user, :admin_group_member, group)
return render_403
diff --git a/app/controllers/groups/avatars_controller.rb b/app/controllers/groups/avatars_controller.rb
index 6aa64222f77..76c87366baa 100644
--- a/app/controllers/groups/avatars_controller.rb
+++ b/app/controllers/groups/avatars_controller.rb
@@ -1,8 +1,6 @@
-class Groups::AvatarsController < ApplicationController
+class Groups::AvatarsController < Groups::ApplicationController
def destroy
- @group = Group.find_by(path: params[:group_id])
@group.remove_avatar!
-
@group.save
redirect_to edit_group_path(@group)
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index 91518c44a98..b25957a06e2 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -1,6 +1,5 @@
class Groups::GroupMembersController < Groups::ApplicationController
skip_before_action :authenticate_user!, only: [:index]
- before_action :group
# Authorize
before_action :authorize_read_group!
@@ -80,10 +79,6 @@ class Groups::GroupMembersController < Groups::ApplicationController
protected
- def group
- @group ||= Group.find_by(path: params[:group_id])
- end
-
def member_params
params.require(:group_member).permit(:access_level, :user_id)
end
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index 669f7f3126d..10233222ee1 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -1,54 +1,55 @@
class Groups::MilestonesController < Groups::ApplicationController
- before_action :authorize_group_milestone!, only: :update
+ include GlobalMilestones
+
+ before_action :projects
+ before_action :milestones, only: [:index]
+ before_action :milestone, only: [:show, :update]
+ before_action :authorize_group_milestone!, only: [:create, :update]
def index
- project_milestones = case params[:state]
- when 'all'; state
- when 'closed'; state('closed')
- else state('active')
- end
- @group_milestones = Milestones::GroupService.new(project_milestones).execute
- @group_milestones = Kaminari.paginate_array(@group_milestones).page(params[:page]).per(PER_PAGE)
end
- def show
- project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC")
- @group_milestone = Milestones::GroupService.new(project_milestones).milestone(title)
+ def new
+ @milestone = Milestone.new
end
- def update
- project_milestones = Milestone.where(project_id: group.projects).order("due_date ASC")
- @group_milestones = Milestones::GroupService.new(project_milestones).milestone(title)
+ def create
+ project_ids = params[:milestone][:project_ids]
+ title = milestone_params[:title]
- @group_milestones.milestones.each do |milestone|
- Milestones::UpdateService.new(milestone.project, current_user, params[:milestone]).execute(milestone)
+ @group.projects.where(id: project_ids).each do |project|
+ Milestones::CreateService.new(project, current_user, milestone_params).execute
end
- respond_to do |format|
- format.js
- format.html do
- redirect_to group_milestones_path(group)
- end
+ redirect_to milestone_path(title)
+ end
+
+ def show
+ end
+
+ def update
+ @milestone.milestones.each do |milestone|
+ Milestones::UpdateService.new(milestone.project, current_user, milestone_params).execute(milestone)
end
+
+ redirect_back_or_default(default: milestone_path(@milestone.title))
end
private
- def group
- @group ||= Group.find_by(path: params[:group_id])
+ def authorize_group_milestone!
+ return render_404 unless can?(current_user, :admin_milestones, group)
end
- def title
- params[:title]
+ def milestone_params
+ params.require(:milestone).permit(:title, :description, :due_date, :state_event)
end
- def state(state = nil)
- conditions = { project_id: group.projects }
- conditions.reverse_merge!(state: state) if state
- Milestone.where(conditions).order("title ASC")
+ def milestone_path(title)
+ group_milestone_path(@group, title.parameterize, title: title)
end
- def authorize_group_milestone!
- return render_404 unless can?(current_user, :admin_group, group)
+ def projects
+ @projects ||= @group.projects
end
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 40fb15a5b36..fb4eb094f27 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -4,12 +4,12 @@ class GroupsController < Groups::ApplicationController
before_action :group, except: [:new, :create]
# Authorize
- before_action :authorize_read_group!, except: [:show, :new, :create]
+ before_action :authorize_read_group!, except: [:show, :new, :create, :autocomplete]
before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects]
before_action :authorize_create_group!, only: [:new, :create]
# Load group projects
- before_action :load_projects, except: [:new, :create, :projects, :edit, :update]
+ before_action :load_projects, except: [:new, :create, :projects, :edit, :update, :autocomplete]
before_action :event_filter, only: :show
layout :determine_layout
@@ -133,7 +133,7 @@ class GroupsController < Groups::ApplicationController
end
def group_params
- params.require(:group).permit(:name, :description, :path, :avatar)
+ params.require(:group).permit(:name, :description, :path, :avatar, :public)
end
def load_events
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index aae77d384c6..67bf4190e7e 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -11,10 +11,6 @@ class Import::GithubController < Import::BaseController
def status
@repos = client.repos
- client.orgs.each do |org|
- @repos += client.org_repos(org.login)
- end
-
@already_added_projects = current_user.created_projects.where(import_type: "github")
already_added_projects_names = @already_added_projects.pluck(:import_source)
diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb
index 41472a6fe6c..e0de31f2251 100644
--- a/app/controllers/import/google_code_controller.rb
+++ b/app/controllers/import/google_code_controller.rb
@@ -10,18 +10,18 @@ class Import::GoogleCodeController < Import::BaseController
dump_file = params[:dump_file]
unless dump_file.respond_to?(:read)
- return redirect_to :back, alert: "You need to upload a Google Takeout archive."
+ return redirect_back_or_default(options: { alert: "You need to upload a Google Takeout archive." })
end
begin
dump = JSON.parse(dump_file.read)
rescue
- return redirect_to :back, alert: "The uploaded file is not a valid Google Takeout archive."
+ return redirect_back_or_default(options: { alert: "The uploaded file is not a valid Google Takeout archive." })
end
client = Gitlab::GoogleCodeImport::Client.new(dump)
unless client.valid?
- return redirect_to :back, alert: "The uploaded file is not a valid Google Takeout archive."
+ return redirect_back_or_default(options: { alert: "The uploaded file is not a valid Google Takeout archive." })
end
session[:google_code_dump] = dump
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index 8ef10a17f55..94bb108c5f5 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -14,7 +14,7 @@ class InvitesController < ApplicationController
redirect_to path, notice: "You have been granted #{member.human_access} access to #{label}."
else
- redirect_to :back, alert: "The invitation could not be accepted."
+ redirect_back_or_default(options: { alert: "The invitation could not be accepted." })
end
end
@@ -31,7 +31,7 @@ class InvitesController < ApplicationController
redirect_to path, notice: "You have declined the invitation to join #{label}."
else
- redirect_to :back, alert: "The invitation could not be declined."
+ redirect_back_or_default(options: { alert: "The invitation could not be declined." })
end
end
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index 22423651c17..1fd1d6882df 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -29,7 +29,7 @@ class Profiles::NotificationsController < Profiles::ApplicationController
flash[:alert] = "Failed to save new settings"
end
- redirect_to :back
+ redirect_back_or_default(default: profile_notifications_path)
end
format.js
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 26a4de15462..8da7b4d50ea 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -26,7 +26,7 @@ class ProfilesController < Profiles::ApplicationController
end
respond_to do |format|
- format.html { redirect_to :back }
+ format.html { redirect_back_or_default(default: { action: 'show' }) }
end
end
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 519d6d6127e..d3f926b62bc 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -29,7 +29,7 @@ class Projects::ApplicationController < ApplicationController
private
def ci_enabled
- return render_404 unless @project.gitlab_ci?
+ return render_404 unless @project.builds_enabled?
end
def ci_project
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index f49c094b591..d7fae64fcdd 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -175,7 +175,7 @@ class Projects::BlobController < Projects::ApplicationController
if params[:file].present?
params[:file_name] = params[:file].original_filename
end
- File.join(@path, File.basename(params[:file_name]))
+ File.join(@path, params[:file_name])
else
@path
end
diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb
index 816012762ce..4638f77b887 100644
--- a/app/controllers/projects/builds_controller.rb
+++ b/app/controllers/projects/builds_controller.rb
@@ -2,23 +2,25 @@ class Projects::BuildsController < Projects::ApplicationController
before_action :ci_project
before_action :build, except: [:index, :cancel_all]
- before_action :authorize_admin_project!, except: [:index, :show, :status]
+ before_action :authorize_manage_builds!, except: [:index, :show, :status]
+ before_action :authorize_download_build_artifacts!, only: [:download]
layout "project"
def index
@scope = params[:scope]
@all_builds = project.ci_builds
+ @builds = @all_builds.order('created_at DESC')
@builds =
case @scope
when 'all'
- @all_builds
+ @builds
when 'finished'
- @all_builds.finished
+ @builds.finished
else
- @all_builds.running_or_pending
+ @builds.running_or_pending.reverse_order
end
- @builds = @builds.order('created_at DESC').page(params[:page]).per(30)
+ @builds = @builds.page(params[:page]).per(30)
end
def cancel_all
@@ -29,7 +31,7 @@ class Projects::BuildsController < Projects::ApplicationController
def show
@builds = @ci_project.commits.find_by_sha(@build.sha).builds.order('id DESC')
- @builds = @builds.where("id not in (?)", @build.id).page(params[:page]).per(20)
+ @builds = @builds.where("id not in (?)", @build.id)
@commit = @build.commit
respond_to do |format|
@@ -41,17 +43,25 @@ class Projects::BuildsController < Projects::ApplicationController
end
def retry
- if @build.commands.blank?
+ unless @build.retryable?
return page_404
end
build = Ci::Build.retry(@build)
- if params[:return_to]
- redirect_to URI.parse(params[:return_to]).path
- else
- redirect_to build_path(build)
+ redirect_to build_path(build)
+ end
+
+ def download
+ unless artifacts_file.file_storage?
+ return redirect_to artifacts_file.url
+ end
+
+ unless artifacts_file.exists?
+ return not_found!
end
+
+ send_file artifacts_file.path, disposition: 'attachment'
end
def status
@@ -70,7 +80,27 @@ class Projects::BuildsController < Projects::ApplicationController
@build ||= ci_project.builds.unscoped.find_by!(id: params[:id])
end
+ def artifacts_file
+ build.artifacts_file
+ end
+
def build_path(build)
namespace_project_build_path(build.gl_project.namespace, build.gl_project, build)
end
+
+ def authorize_manage_builds!
+ unless can?(current_user, :manage_builds, project)
+ return page_404
+ end
+ end
+
+ def authorize_download_build_artifacts!
+ unless can?(current_user, :download_build_artifacts, @project)
+ if current_user.nil?
+ return authenticate_user!
+ else
+ return render_404
+ end
+ end
+ end
end
diff --git a/app/controllers/projects/ci_services_controller.rb b/app/controllers/projects/ci_services_controller.rb
index 6d2756eba3d..550a019e8e2 100644
--- a/app/controllers/projects/ci_services_controller.rb
+++ b/app/controllers/projects/ci_services_controller.rb
@@ -14,23 +14,23 @@ class Projects::CiServicesController < Projects::ApplicationController
end
def update
- if @service.update_attributes(service_params)
- redirect_to edit_namespace_project_ci_service_path(@project, @project.namespace, @service.to_param)
+ if service.update_attributes(service_params)
+ redirect_to edit_namespace_project_ci_service_path(@project.namespace, @project, service.to_param)
else
render 'edit'
end
end
def test
- last_build = @project.builds.last
+ last_build = @project.ci_builds.last
- if @service.execute(last_build)
+ if service.execute(last_build)
message = { notice: 'We successfully tested the service' }
else
message = { alert: 'We tried to test the service but error occurred' }
end
- redirect_to :back, message
+ redirect_back_or_default(options: message)
end
private
diff --git a/app/controllers/projects/ci_web_hooks_controller.rb b/app/controllers/projects/ci_web_hooks_controller.rb
index 7f40ddcb3f3..a2d470d4a69 100644
--- a/app/controllers/projects/ci_web_hooks_controller.rb
+++ b/app/controllers/projects/ci_web_hooks_controller.rb
@@ -24,7 +24,7 @@ class Projects::CiWebHooksController < Projects::ApplicationController
def test
Ci::TestHookService.new.execute(hook, current_user)
- redirect_to :back
+ redirect_back_or_default(default: { action: 'index' })
end
def destroy
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 7886f3c6deb..deefdd76667 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -4,16 +4,17 @@
class Projects::CommitController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
- before_action :authorize_download_code!
+ before_action :authorize_download_code!, except: [:cancel_builds]
+ before_action :authorize_manage_builds!, only: [:cancel_builds]
before_action :commit
+ before_action :authorize_manage_builds!, only: [:cancel_builds, :retry_builds]
+ before_action :define_show_vars, only: [:show, :builds]
def show
return git_not_found! unless @commit
@line_notes = commit.notes.inline
- @diffs = @commit.diffs
@note = @project.build_commit_note(commit)
- @notes_count = commit.notes.count
@notes = commit.notes.not_inline.fresh
@noteable = @commit
@comments_allowed = @reply_allowed = true
@@ -22,8 +23,6 @@ class Projects::CommitController < Projects::ApplicationController
commit_id: @commit.id
}
- @ci_commit = project.ci_commit(commit.sha)
-
respond_to do |format|
format.html
format.diff { render text: @commit.to_diff }
@@ -31,20 +30,25 @@ class Projects::CommitController < Projects::ApplicationController
end
end
- def ci
- @ci_commit = @project.ci_commit(@commit.sha)
- @builds = @ci_commit.builds if @ci_commit
- @notes_count = @commit.notes.count
+ def builds
@ci_project = @project.gitlab_ci_project
end
def cancel_builds
- @ci_commit = @project.ci_commit(@commit.sha)
- @ci_commit.builds.running_or_pending.each(&:cancel)
+ ci_commit.builds.running_or_pending.each(&:cancel)
- redirect_to ci_namespace_project_commit_path(project.namespace, project, commit.sha)
+ redirect_to builds_namespace_project_commit_path(project.namespace, project, commit.sha)
end
+ def retry_builds
+ ci_commit.builds.latest.failed.each do |build|
+ if build.retryable?
+ Ci::Build.retry(build)
+ end
+ end
+
+ redirect_to builds_namespace_project_commit_path(project.namespace, project, commit.sha)
+ end
def branches
@branches = @project.repository.branch_names_contains(commit.id)
@@ -52,7 +56,26 @@ class Projects::CommitController < Projects::ApplicationController
render layout: false
end
+ private
+
def commit
@commit ||= @project.commit(params[:id])
end
+
+ def ci_commit
+ @ci_commit ||= project.ci_commit(commit.sha)
+ end
+
+ def define_show_vars
+ @diffs = commit.diffs
+ @notes_count = commit.notes.count
+
+ @builds = ci_commit.builds if ci_commit
+ end
+
+ def authorize_manage_builds!
+ unless can?(current_user, :manage_builds, project)
+ return page_404
+ end
+ end
end
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index d1c15174aea..58fb946dbc2 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -12,7 +12,7 @@ class Projects::CommitsController < Projects::ApplicationController
@limit, @offset = (params[:limit] || 40), (params[:offset] || 0)
@commits = @repo.commits(@ref, @path, @limit, @offset)
- @note_counts = Note.where(commit_id: @commits.map(&:id)).
+ @note_counts = project.notes.where(commit_id: @commits.map(&:id)).
group(:commit_id).count
respond_to do |format|
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index d15004f93a6..55134e11d15 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -12,14 +12,16 @@ class Projects::CompareController < Projects::ApplicationController
def show
base_ref = Addressable::URI.unescape(params[:from])
@ref = head_ref = Addressable::URI.unescape(params[:to])
+ diff_options = { ignore_whitespace_change: true } if params[:w] == '1'
compare_result = CompareService.new.
- execute(@project, head_ref, @project, base_ref)
+ execute(@project, head_ref, @project, base_ref, diff_options)
if compare_result
- @commits = compare_result.commits
+ @commits = Commit.decorate(compare_result.commits, @project)
@diffs = compare_result.diffs
@commit = @commits.last
+ @first_commit = @commits.first
@line_notes = []
end
end
diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb
index 40e2b37912b..7d09288bc80 100644
--- a/app/controllers/projects/deploy_keys_controller.rb
+++ b/app/controllers/projects/deploy_keys_controller.rb
@@ -46,7 +46,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
def disable
@project.deploy_keys_projects.find_by(deploy_key_id: params[:id]).destroy
- redirect_to :back
+ redirect_back_or_default(default: { action: 'index' })
end
protected
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index 4e5b4125f5a..c7569541899 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -37,7 +37,7 @@ class Projects::HooksController < Projects::ApplicationController
flash[:alert] = 'Hook execution failed. Ensure the project has commits.'
end
- redirect_to :back
+ redirect_back_or_default(default: { action: 'index' })
end
def destroy
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 97485c101fb..e74c2905e48 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -14,6 +14,9 @@ class Projects::IssuesController < Projects::ApplicationController
# Allow issues bulk update
before_action :authorize_admin_issues!, only: [:bulk_update]
+ # Cross-reference merge requests
+ before_action :closed_by_merge_requests, only: [:show]
+
respond_to :html
def index
@@ -103,7 +106,7 @@ class Projects::IssuesController < Projects::ApplicationController
def bulk_update
result = Issues::BulkUpdateService.new(project, current_user, bulk_update_params).execute
- redirect_to :back, notice: "#{result[:count]} issues updated"
+ redirect_back_or_default(default: { action: 'index' }, options: { notice: "#{result[:count]} issues updated" })
end
def toggle_subscription
@@ -112,6 +115,10 @@ class Projects::IssuesController < Projects::ApplicationController
render nothing: true
end
+ def closed_by_merge_requests
+ @closed_by_merge_requests ||= @issue.closed_by_merge_requests(current_user)
+ end
+
protected
def issue
@@ -151,10 +158,12 @@ class Projects::IssuesController < Projects::ApplicationController
end
def issue_params
- params.require(:issue).permit(
+ permitted = params.require(:issue).permit(
:title, :assignee_id, :position, :description,
:milestone_id, :state_event, :task_num, label_ids: []
)
+ params[:issue][:title].strip! if params[:issue][:title]
+ permitted
end
def bulk_update_params
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 98df6984bf7..188f0cc4cea 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -31,6 +31,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
@merge_requests = @merge_requests.page(params[:page]).per(PER_PAGE)
+ @merge_requests = @merge_requests.preload(:target_project)
respond_to do |format|
format.html
@@ -56,6 +57,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def diffs
@commit = @merge_request.last_commit
+ @first_commit = @merge_request.first_commit
+
@comments_allowed = @reply_allowed = true
@comments_target = {
noteable_type: 'MergeRequest',
@@ -89,7 +92,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@target_project = merge_request.target_project
@source_project = merge_request.source_project
@commits = @merge_request.compare_commits
- @commit = @merge_request.compare_commits.last
+ @commit = @merge_request.last_commit
+ @first_commit = @merge_request.first_commit
@diffs = @merge_request.compare_diffs
@note_counts = Note.where(commit_id: @commits.map(&:id)).
group(:commit_id).count
@@ -259,7 +263,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@commits = @merge_request.commits
@merge_request_diff = @merge_request.merge_request_diff
-
+
if @merge_request.locked_long_ago?
@merge_request.unlock_mr
@merge_request.close
@@ -272,11 +276,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
def merge_request_params
- params.require(:merge_request).permit(
+ permitted = params.require(:merge_request).permit(
:title, :assignee_id, :source_project_id, :source_branch,
:target_project_id, :target_branch, :milestone_id,
:state_event, :description, :task_num, label_ids: []
)
+ params[:merge_request][:title].strip! if params[:merge_request][:title]
+ permitted
end
# Make sure merge requests created before 8.0
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index 86f4a02a6e9..15506bd677a 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -75,11 +75,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end
def sort_issues
- @issues = @milestone.issues.where(id: params['sortable_issue'])
- @issues.each do |issue|
- issue.position = params['sortable_issue'].index(issue.id.to_s) + 1
- issue.save
- end
+ @milestone.sort_issues(params['sortable_issue'].map(&:to_i))
render json: { saved: true }
end
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index 0f5d82ce133..41cd08c93c6 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -25,7 +25,7 @@ class Projects::NotesController < Projects::ApplicationController
respond_to do |format|
format.json { render_note_json(@note) }
- format.html { redirect_to :back }
+ format.html { redirect_back_or_default }
end
end
@@ -34,7 +34,7 @@ class Projects::NotesController < Projects::ApplicationController
respond_to do |format|
format.json { render_note_json(@note) }
- format.html { redirect_to :back }
+ format.html { redirect_back_or_default }
end
end
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index cf73bc01c8f..9de5269cd25 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -72,7 +72,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController
def leave
if @project.namespace == current_user.namespace
- return redirect_to(:back, alert: 'You can not leave your own project. Transfer or delete the project.')
+ message = 'You can not leave your own project. Transfer or delete the project.'
+ return redirect_back_or_default(default: { action: 'index' }, options: { alert: message })
end
@project.project_members.find_by(user_id: current_user).destroy
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
new file mode 100644
index 00000000000..0825a4311cb
--- /dev/null
+++ b/app/controllers/projects/releases_controller.rb
@@ -0,0 +1,31 @@
+class Projects::ReleasesController < Projects::ApplicationController
+ # Authorize
+ before_action :require_non_empty_project
+ before_action :authorize_download_code!
+ before_action :authorize_push_code!
+ before_action :tag
+ before_action :release
+
+ def edit
+ end
+
+ def update
+ release.update_attributes(release_params)
+
+ redirect_to namespace_project_tag_path(@project.namespace, @project, @tag.name)
+ end
+
+ private
+
+ def tag
+ @tag ||= @repository.find_tag(params[:tag_id])
+ end
+
+ def release
+ @release ||= @project.releases.find_or_initialize_by(tag: @tag.name)
+ end
+
+ def release_params
+ params.require(:release).permit(:description)
+ end
+end
diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb
index deb07a21416..bfbcf2567f3 100644
--- a/app/controllers/projects/runners_controller.rb
+++ b/app/controllers/projects/runners_controller.rb
@@ -6,11 +6,10 @@ class Projects::RunnersController < Projects::ApplicationController
layout 'project_settings'
def index
- @runners = @ci_project.runners.order('id DESC')
- @specific_runners =
- Ci::Runner.specific.includes(:runner_projects).
- where(Ci::RunnerProject.table_name => { project_id: current_user.authorized_projects } ).
- where.not(id: @runners).order("#{Ci::Runner.table_name}.id DESC").page(params[:page]).per(20)
+ @runners = @ci_project.runners.ordered
+ @specific_runners = current_user.ci_authorized_runners.
+ where.not(id: @ci_project.runners).
+ ordered.page(params[:page]).per(20)
@shared_runners = Ci::Runner.shared.active
@shared_runners_count = @shared_runners.count(:all)
end
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index 129068ef019..42dbb497e01 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -12,7 +12,7 @@ class Projects::ServicesController < Projects::ApplicationController
# Parameters to ignore if no value is specified
FILTER_BLANK_PARAMS = [:password]
-
+
# Authorize
before_action :authorize_admin_project!
before_action :service, only: [:edit, :update, :test]
@@ -52,7 +52,7 @@ class Projects::ServicesController < Projects::ApplicationController
message = { alert: error_message }
end
- redirect_to :back, message
+ redirect_back_or_default(options: message)
end
private
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index b07a2a8db2f..2104c7a7a71 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -21,6 +21,7 @@ class Projects::SnippetsController < Projects::ApplicationController
filter: :by_project,
project: @project
})
+ @snippets = @snippets.page(params[:page]).per(PER_PAGE)
end
def new
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index f565fbbbbc3..cb39c2b8782 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -8,15 +8,23 @@ class Projects::TagsController < Projects::ApplicationController
def index
sorted = VersionSorter.rsort(@repository.tag_names)
@tags = Kaminari.paginate_array(sorted).page(params[:page]).per(PER_PAGE)
+ @releases = project.releases.where(tag: @tags)
+ end
+
+ def show
+ @tag = @repository.find_tag(params[:id])
+ @release = @project.releases.find_or_initialize_by(tag: @tag.name)
+ @commit = @repository.commit(@tag.target)
end
def create
result = CreateTagService.new(@project, current_user).
- execute(params[:tag_name], params[:ref], params[:message])
+ execute(params[:tag_name], params[:ref], params[:message], params[:release_description])
if result[:status] == :success
@tag = result[:tag]
- redirect_to namespace_project_tags_path(@project.namespace, @project)
+
+ redirect_to namespace_project_tag_path(@project.namespace, @project, @tag.name)
else
@error = result[:message]
render action: 'new'
@@ -26,12 +34,6 @@ class Projects::TagsController < Projects::ApplicationController
def destroy
DeleteTagService.new(project, current_user).execute(params[:id])
- respond_to do |format|
- format.html do
- redirect_to namespace_project_tags_path(@project.namespace,
- @project)
- end
- format.js
- end
+ redirect_to namespace_project_tags_path(@project.namespace, @project)
end
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 213c2a7173b..23453195e85 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -1,11 +1,14 @@
class ProjectsController < ApplicationController
- prepend_before_filter :render_go_import, only: [:show]
+ include ExtractsPath
+
+ prepend_before_action :render_go_import, only: [:show]
skip_before_action :authenticate_user!, only: [:show, :activity]
before_action :project, except: [:new, :create]
before_action :repository, except: [:new, :create]
+ before_action :assign_ref_vars, :tree, only: [:show], if: :repo_exists?
# Authorize
- before_action :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive]
+ before_action :authorize_admin_project!, only: [:edit, :update]
before_action :event_filter, only: [:show, :activity]
layout :determine_layout
@@ -56,6 +59,8 @@ class ProjectsController < ApplicationController
end
def transfer
+ return access_denied! unless can?(current_user, :change_namespace, @project)
+
namespace = Namespace.find_by(id: params[:new_namespace_id])
::Projects::TransferService.new(project, current_user).execute(namespace)
@@ -64,6 +69,14 @@ class ProjectsController < ApplicationController
end
end
+ def remove_fork
+ return access_denied! unless can?(current_user, :remove_fork_project, @project)
+
+ if @project.unlink_fork
+ flash[:notice] = 'The fork relationship has been removed.'
+ end
+ end
+
def activity
respond_to do |format|
format.html
@@ -87,7 +100,7 @@ class ProjectsController < ApplicationController
render 'projects/empty'
else
if current_user
- @membership = @project.project_member_by_id(current_user.id)
+ @membership = @project.team.find_member(current_user.id)
end
render :show
@@ -110,11 +123,7 @@ class ProjectsController < ApplicationController
::Projects::DestroyService.new(@project, current_user, {}).execute
flash[:alert] = "Project '#{@project.name}' was deleted."
- if request.referer.include?('/admin')
- redirect_to admin_namespaces_projects_path
- else
- redirect_to dashboard_projects_path
- end
+ redirect_back_or_default(default: dashboard_projects_path, options: {})
rescue Projects::DestroyService::DestroyError => ex
redirect_to edit_project_path(@project), alert: ex.message
end
@@ -139,6 +148,7 @@ class ProjectsController < ApplicationController
def archive
return access_denied! unless can?(current_user, :archive_project, @project)
+
@project.archive!
respond_to do |format|
@@ -148,6 +158,7 @@ class ProjectsController < ApplicationController
def unarchive
return access_denied! unless can?(current_user, :archive_project, @project)
+
@project.unarchive!
respond_to do |format|
@@ -201,7 +212,8 @@ class ProjectsController < ApplicationController
params.require(:project).permit(
:name, :path, :description, :issues_tracker, :tag_list,
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch,
- :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar
+ :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar,
+ :builds_enabled
)
end
@@ -225,4 +237,14 @@ class ProjectsController < ApplicationController
render "go_import", layout: false
end
+
+ def repo_exists?
+ project.repository_exists? && !project.empty_repo?
+ end
+
+ # Override get_id from ExtractsPath, which returns the branch and file path
+ # for the blob/tree, which in this case is just the root of the default branch.
+ def get_id
+ project.repository.root_ref
+ end
end
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index eb0408a95e5..9bb42ec86b3 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -23,8 +23,8 @@ class SearchController < ApplicationController
@search_results =
if @project
- unless %w(blobs notes issues merge_requests milestones wiki_blobs).
- include?(@scope)
+ unless %w(blobs notes issues merge_requests milestones wiki_blobs
+ commits).include?(@scope)
@scope = 'blobs'
end
diff --git a/app/controllers/sherlock/application_controller.rb b/app/controllers/sherlock/application_controller.rb
new file mode 100644
index 00000000000..682ca5e3821
--- /dev/null
+++ b/app/controllers/sherlock/application_controller.rb
@@ -0,0 +1,12 @@
+module Sherlock
+ class ApplicationController < ::ApplicationController
+ before_action :find_transaction
+
+ def find_transaction
+ if params[:transaction_id]
+ @transaction = Gitlab::Sherlock.collection.
+ find_transaction(params[:transaction_id])
+ end
+ end
+ end
+end
diff --git a/app/controllers/sherlock/file_samples_controller.rb b/app/controllers/sherlock/file_samples_controller.rb
new file mode 100644
index 00000000000..0c3bc100106
--- /dev/null
+++ b/app/controllers/sherlock/file_samples_controller.rb
@@ -0,0 +1,7 @@
+module Sherlock
+ class FileSamplesController < Sherlock::ApplicationController
+ def show
+ @file_sample = @transaction.find_file_sample(params[:id])
+ end
+ end
+end
diff --git a/app/controllers/sherlock/queries_controller.rb b/app/controllers/sherlock/queries_controller.rb
new file mode 100644
index 00000000000..63b26aab1a4
--- /dev/null
+++ b/app/controllers/sherlock/queries_controller.rb
@@ -0,0 +1,7 @@
+module Sherlock
+ class QueriesController < Sherlock::ApplicationController
+ def show
+ @query = @transaction.find_query(params[:id])
+ end
+ end
+end
diff --git a/app/controllers/sherlock/transactions_controller.rb b/app/controllers/sherlock/transactions_controller.rb
new file mode 100644
index 00000000000..ccc739da879
--- /dev/null
+++ b/app/controllers/sherlock/transactions_controller.rb
@@ -0,0 +1,19 @@
+module Sherlock
+ class TransactionsController < Sherlock::ApplicationController
+ def index
+ @transactions = Gitlab::Sherlock.collection.newest_first
+ end
+
+ def show
+ @transaction = Gitlab::Sherlock.collection.find_transaction(params[:id])
+
+ render_404 unless @transaction
+ end
+
+ def destroy_all
+ Gitlab::Sherlock.collection.clear
+
+ redirect_to(:back)
+ end
+ end
+end
diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb
index d3597ef0901..b5f3176461c 100644
--- a/app/finders/groups_finder.rb
+++ b/app/finders/groups_finder.rb
@@ -6,33 +6,34 @@ class GroupsFinder
private
def all_groups(current_user)
- if current_user
- if current_user.authorized_groups.any?
- # User has access to groups
- #
- # Return only:
- # groups with public projects
- # groups with internal projects
- # groups with joined projects
- #
- group_ids = Project.public_and_internal_only.pluck(:namespace_id) +
- current_user.authorized_groups.pluck(:id)
- Group.where(id: group_ids)
- else
- # User has no group membership
- #
- # Return only:
- # groups with public projects
- # groups with internal projects
- #
- Group.where(id: Project.public_and_internal_only.pluck(:namespace_id))
- end
- else
- # Not authenticated
- #
- # Return only:
- # groups with public projects
- Group.where(id: Project.public_only.pluck(:namespace_id))
- end
+ group_ids = if current_user
+ if current_user.authorized_groups.any?
+ # User has access to groups
+ #
+ # Return only:
+ # groups with public projects
+ # groups with internal projects
+ # groups with joined projects
+ #
+ Project.public_and_internal_only.pluck(:namespace_id) +
+ current_user.authorized_groups.pluck(:id)
+ else
+ # User has no group membership
+ #
+ # Return only:
+ # groups with public projects
+ # groups with internal projects
+ #
+ Project.public_and_internal_only.pluck(:namespace_id)
+ end
+ else
+ # Not authenticated
+ #
+ # Return only:
+ # groups with public projects
+ Project.public_only.pluck(:namespace_id)
+ end
+
+ Group.where("public IS TRUE OR id IN(?)", group_ids)
end
end
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 97c7e74c294..c407dfc163a 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -53,15 +53,36 @@ class IssuableFinder
end
end
+ def project?
+ params[:project_id].present?
+ end
+
def project
return @project if defined?(@project)
- @project =
- if params[:project_id].present?
- Project.find(params[:project_id])
- else
- nil
- end
+ if project?
+ @project = Project.find(params[:project_id])
+
+ unless Ability.abilities.allowed?(current_user, :read_project, @project)
+ @project = nil
+ end
+ else
+ @project = nil
+ end
+
+ @project
+ end
+
+ def projects
+ return @projects if defined?(@projects)
+
+ if project?
+ project
+ elsif current_user && params[:authorized_only].presence && !current_user_related?
+ current_user.authorized_projects
+ else
+ ProjectsFinder.new.execute(current_user)
+ end
end
def search
@@ -72,7 +93,7 @@ class IssuableFinder
params[:milestone_title].present?
end
- def no_milestones?
+ def filter_by_no_milestone?
milestones? && params[:milestone_title] == Milestone::None.title
end
@@ -81,12 +102,22 @@ class IssuableFinder
@milestones =
if milestones?
- Milestone.where(title: params[:milestone_title])
+ scope = Milestone.where(project_id: projects)
+
+ scope.where(title: params[:milestone_title])
else
nil
end
end
+ def labels?
+ params[:label_name].present?
+ end
+
+ def filter_by_no_label?
+ labels? && params[:label_name] == Label::None.title
+ end
+
def assignee?
params[:assignee_id].present?
end
@@ -120,19 +151,7 @@ class IssuableFinder
private
def init_collection
- table_name = klass.table_name
-
- if project
- if Ability.abilities.allowed?(current_user, :read_project, project)
- project.send(table_name)
- else
- []
- end
- elsif current_user && params[:authorized_only].presence && !current_user_related?
- klass.of_projects(current_user.authorized_projects).references(:project)
- else
- klass.of_projects(ProjectsFinder.new.execute(current_user)).references(:project)
- end
+ klass.all
end
def by_scope(items)
@@ -170,7 +189,12 @@ class IssuableFinder
end
def by_project(items)
- items = items.of_projects(project.id) if project
+ items =
+ if projects
+ items.of_projects(projects).references(:project)
+ else
+ items.none
+ end
items
end
@@ -185,18 +209,6 @@ class IssuableFinder
items.sort(params[:sort])
end
- def by_milestone(items)
- if milestones?
- if no_milestones?
- items = items.where(milestone_id: [-1, nil])
- else
- items = items.where(milestone_id: milestones.try(:pluck, :id))
- end
- end
-
- items
- end
-
def by_assignee(items)
if assignee?
items = items.where(assignee_id: assignee.try(:id))
@@ -213,20 +225,36 @@ class IssuableFinder
items
end
- def by_label(items)
- if params[:label_name].present?
- if params[:label_name] == Label::None.title
- item_ids = LabelLink.where(target_type: klass.name).pluck(:target_id)
+ def by_milestone(items)
+ if milestones?
+ if filter_by_no_milestone?
+ items = items.where(milestone_id: [-1, nil])
+ else
+ items = items.joins(:milestone).where(milestones: { title: params[:milestone_title] })
+
+ if projects
+ items = items.where(milestones: { project_id: projects })
+ end
+ end
+ end
+
+ items
+ end
- items = items.where('id NOT IN (?)', item_ids)
+ def by_label(items)
+ if labels?
+ if filter_by_no_label?
+ items = items.
+ joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{klass.name}' AND label_links.target_id = #{klass.table_name}.id").
+ where(label_links: { id: nil })
else
label_names = params[:label_name].split(",")
- item_ids = LabelLink.joins(:label).
- where('labels.title in (?)', label_names).
- where(target_type: klass.name).pluck(:target_id)
+ items = items.joins(:labels).where(labels: { title: label_names })
- items = items.where(id: item_ids)
+ if projects
+ items = items.where(labels: { project_id: projects })
+ end
end
end
diff --git a/app/finders/milestones_finder.rb b/app/finders/milestones_finder.rb
new file mode 100644
index 00000000000..b704e878903
--- /dev/null
+++ b/app/finders/milestones_finder.rb
@@ -0,0 +1,12 @@
+class MilestonesFinder
+ def execute(projects, params)
+ milestones = Milestone.of_projects(projects)
+ milestones = milestones.order("due_date ASC")
+
+ case params[:state]
+ when 'closed' then milestones.closed
+ when 'all' then milestones
+ else milestones.active
+ end
+ end
+end
diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb
index 14df8d4cbd7..c5820bf4c50 100644
--- a/app/helpers/appearances_helper.rb
+++ b/app/helpers/appearances_helper.rb
@@ -16,6 +16,6 @@ module AppearancesHelper
end
def brand_header_logo
- image_tag 'logo.svg'
+ render 'shared/logo.svg'
end
end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index cd99a232403..2c81ea1623c 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -1,5 +1,5 @@
module AuthHelper
- PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2).freeze
+ PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook).freeze
FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze
def ldap_enabled?
diff --git a/app/helpers/builds_helper.rb b/app/helpers/builds_helper.rb
deleted file mode 100644
index 1b5a2c31d74..00000000000
--- a/app/helpers/builds_helper.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-module BuildsHelper
- def build_ref_link build
- gitlab_ref_link build.project, build.ref
- end
-
- def build_commit_link build
- gitlab_commit_link build.project, build.short_sha
- end
-
- def build_url(build)
- namespace_project_build_path(build.gl_project, build.project, build)
- end
-end
diff --git a/app/helpers/ci/gitlab_helper.rb b/app/helpers/ci/gitlab_helper.rb
index baddbc806f2..e34c8be1dfc 100644
--- a/app/helpers/ci/gitlab_helper.rb
+++ b/app/helpers/ci/gitlab_helper.rb
@@ -4,25 +4,6 @@ module Ci
{ :"data-no-turbolink" => "data-no-turbolink" }
end
- def gitlab_ref_link project, ref
- gitlab_url = project.gitlab_url.dup
- gitlab_url << "/commits/#{ref}"
- link_to ref, gitlab_url, no_turbolink
- end
-
- def gitlab_compare_link project, before, after
- gitlab_url = project.gitlab_url.dup
- gitlab_url << "/compare/#{before}...#{after}"
-
- link_to "#{before}...#{after}", gitlab_url, no_turbolink
- end
-
- def gitlab_commit_link project, sha
- gitlab_url = project.gitlab_url.dup
- gitlab_url << "/commit/#{sha}"
- link_to Ci::Commit.truncate_sha(sha), gitlab_url, no_turbolink
- end
-
def yaml_web_editor_link(project)
commits = project.commits
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index dbd1e26fa79..0ecf77bb45e 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -1,7 +1,7 @@
module CiStatusHelper
def ci_status_path(ci_commit)
project = ci_commit.gl_project
- ci_namespace_project_commit_path(project.namespace, project, ci_commit.sha)
+ builds_namespace_project_commit_path(project.namespace, project, ci_commit.sha)
end
def ci_status_icon(ci_commit)
@@ -42,4 +42,13 @@ module CiStatusHelper
icon(icon_name)
end
+
+ def render_ci_status(ci_commit)
+ link_to ci_status_path(ci_commit),
+ class: "c#{ci_status_color(ci_commit)}",
+ title: "Build status: #{ci_commit.status}",
+ data: { toggle: 'tooltip', placement: 'left' } do
+ ci_status_icon(ci_commit)
+ end
+ end
end
diff --git a/app/helpers/clipboard_helper.rb b/app/helpers/clipboard_helper.rb
new file mode 100644
index 00000000000..3c1d7569fac
--- /dev/null
+++ b/app/helpers/clipboard_helper.rb
@@ -0,0 +1,8 @@
+module ClipboardHelper
+ def clipboard_button
+ content_tag :button,
+ icon('clipboard'),
+ class: 'btn btn-xs btn-clipboard js-clipboard-trigger',
+ type: :button
+ end
+end
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index b896fba3704..b889fb28973 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -137,7 +137,7 @@ module DiffHelper
# Always use HTML to handle case where JSON diff rendered this button
params_copy.delete(:format)
- link_to url_for(params_copy), id: "inline-diff-btn", class: (params[:view] != 'parallel' ? 'btn btn-sm active' : 'btn btn-sm') do
+ link_to url_for(params_copy), id: "inline-diff-btn", class: (params[:view] != 'parallel' ? 'btn active' : 'btn') do
'Inline'
end
end
@@ -148,7 +148,7 @@ module DiffHelper
# Always use HTML to handle case where JSON diff rendered this button
params_copy.delete(:format)
- link_to url_for(params_copy), id: "parallel-diff-btn", class: (params[:view] == 'parallel' ? 'btn active btn-sm' : 'btn btn-sm') do
+ link_to url_for(params_copy), id: "parallel-diff-btn", class: (params[:view] == 'parallel' ? 'btn active' : 'btn') do
'Side-by-side'
end
end
@@ -170,7 +170,8 @@ module DiffHelper
def commit_for_diff(diff)
if diff.deleted_file
- @merge_request ? @merge_request.commits.last : @commit.parents.first
+ first_commit = @first_commit || @commit
+ first_commit.parent
else
@commit
end
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 6f69c2a9f32..dde83ff36b5 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -108,19 +108,23 @@ module EventsHelper
end
end
elsif event.push?
- if event.push_with_commits? && event.md_ref?
- if event.commits_count > 1
- namespace_project_compare_url(event.project.namespace, event.project,
- from: event.commit_from, to:
- event.commit_to)
- else
- namespace_project_commit_url(event.project.namespace, event.project,
- id: event.commit_to)
- end
+ push_event_feed_url(event)
+ end
+ end
+
+ def push_event_feed_url(event)
+ if event.push_with_commits? && event.md_ref?
+ if event.commits_count > 1
+ namespace_project_compare_url(event.project.namespace, event.project,
+ from: event.commit_from, to:
+ event.commit_to)
else
- namespace_project_commits_url(event.project.namespace, event.project,
- event.ref_name)
+ namespace_project_commit_url(event.project.namespace, event.project,
+ id: event.commit_to)
end
+ else
+ namespace_project_commits_url(event.project.namespace, event.project,
+ event.ref_name)
end
end
@@ -198,7 +202,7 @@ module EventsHelper
xml.link href: event_link
xml.title truncate(event_title, length: 80)
xml.updated event.created_at.xmlschema
- xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(event.author_email)
+ xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(event.author_email))
xml.author do |author|
xml.name event.author_name
xml.email event.author_email
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index 12b87dca798..65813482120 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -19,7 +19,8 @@ module GitlabMarkdownHelper
escape_once(body)
end
- gfm_body = Gitlab::Markdown.gfm(escaped_body, project: @project, current_user: current_user)
+ user = current_user if defined?(current_user)
+ gfm_body = Gitlab::Markdown.gfm(escaped_body, project: @project, current_user: user)
fragment = Nokogiri::HTML::DocumentFragment.parse(gfm_body)
if fragment.children.size == 1 && fragment.children[0].name == 'a'
@@ -45,29 +46,39 @@ module GitlabMarkdownHelper
end
def markdown(text, context = {})
+ return "" unless text.present?
+
context.reverse_merge!(
- current_user: current_user,
path: @path,
+ pipeline: :default,
project: @project,
project_wiki: @project_wiki,
ref: @ref
)
- Gitlab::Markdown.render(text, context)
+ user = current_user if defined?(current_user)
+
+ html = Gitlab::Markdown.render(text, context)
+ Gitlab::Markdown.post_process(html, pipeline: context[:pipeline], project: @project, user: user)
end
# TODO (rspeicher): Remove all usages of this helper and just call `markdown`
# with a custom pipeline depending on the content being rendered
def gfm(text, options = {})
+ return "" unless text.present?
+
options.reverse_merge!(
- current_user: current_user,
path: @path,
+ pipeline: :default,
project: @project,
project_wiki: @project_wiki,
ref: @ref
)
- Gitlab::Markdown.gfm(text, options)
+ user = current_user if defined?(current_user)
+
+ html = Gitlab::Markdown.gfm(text, options)
+ Gitlab::Markdown.post_process(html, pipeline: options[:pipeline], project: @project, user: user)
end
def asciidoc(text)
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index 6ddb37cd0dc..beb083d82dc 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -74,7 +74,7 @@ module IssuesHelper
issue.project, issue)
xml.title truncate(issue.title, length: 80)
xml.updated issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")
- xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(issue.author_email)
+ xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(issue.author_email))
xml.author do |author|
xml.name issue.author_name
xml.email issue.author_email
@@ -83,6 +83,10 @@ module IssuesHelper
end
end
+ def merge_requests_sentence(merge_requests)
+ merge_requests.map(&:to_reference).to_sentence(last_word_connector: ', or ')
+ end
+
# Required for Gitlab::Markdown::IssueReferenceFilter
module_function :url_for_issue
end
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 66b18eea699..795fb439f25 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -92,11 +92,19 @@ module LabelsHelper
end
end
- def project_labels_options(project)
- labels = project.labels.to_a
- labels.unshift(Label::None)
- labels.unshift(Label::Any)
- options_from_collection_for_select(labels, 'name', 'title', params[:label_name])
+ def projects_labels_options
+ labels =
+ if @project
+ @project.labels
+ else
+ Label.where(project_id: @projects)
+ end
+
+ grouped_labels = GlobalLabel.build_collection(labels)
+ grouped_labels.unshift(Label::None)
+ grouped_labels.unshift(Label::Any)
+
+ options_from_collection_for_select(grouped_labels, 'name', 'title', params[:label_name])
end
# Required for Gitlab::Markdown::LabelReferenceFilter
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 37a5b58cce8..ad43892b639 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -28,7 +28,7 @@ module MilestonesHelper
Milestone.where(project_id: @projects)
end.active
- grouped_milestones = Milestones::GroupService.new(milestones).execute
+ grouped_milestones = GlobalMilestone.build_collection(milestones)
grouped_milestones.unshift(Milestone::None)
grouped_milestones.unshift(Milestone::Any)
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index cf11f8e5320..499c655d2bf 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -16,40 +16,28 @@ module NotificationsHelper
def notification_list_item(notification_level, user_membership)
case notification_level
when Notification::N_DISABLED
- content_tag(:li, class: active_level_for(user_membership, Notification::N_DISABLED)) do
- link_to '#', class: 'update-notification', data: { notification_level: Notification::N_DISABLED } do
- icon('microphone-slash fw', text: 'Disabled')
- end
- end
+ update_notification_link(Notification::N_DISABLED, user_membership, 'Disabled', 'microphone-slash')
when Notification::N_PARTICIPATING
- content_tag(:li, class: active_level_for(user_membership, Notification::N_PARTICIPATING)) do
- link_to '#', class: 'update-notification', data: { notification_level: Notification::N_PARTICIPATING } do
- icon('volume-up fw', text: 'Participate')
- end
- end
+ update_notification_link(Notification::N_PARTICIPATING, user_membership, 'Participate', 'volume-up')
when Notification::N_WATCH
- content_tag(:li, class: active_level_for(user_membership, Notification::N_WATCH)) do
- link_to '#', class: 'update-notification', data: { notification_level: Notification::N_WATCH } do
- icon('eye fw', text: 'Watch')
- end
- end
+ update_notification_link(Notification::N_WATCH, user_membership, 'Watch', 'eye')
when Notification::N_MENTION
- content_tag(:li, class: active_level_for(user_membership, Notification::N_MENTION)) do
- link_to '#', class: 'update-notification', data: { notification_level: Notification::N_MENTION } do
- icon('at fw', text: 'On mention')
- end
- end
+ update_notification_link(Notification::N_MENTION, user_membership, 'On mention', 'at')
when Notification::N_GLOBAL
- content_tag(:li, class: active_level_for(user_membership, Notification::N_GLOBAL)) do
- link_to '#', class: 'update-notification', data: { notification_level: Notification::N_GLOBAL } do
- icon('globe fw', text: 'Global')
- end
- end
+ update_notification_link(Notification::N_GLOBAL, user_membership, 'Global', 'globe')
else
# do nothing
end
end
+ def update_notification_link(notification_level, user_membership, title, icon)
+ content_tag(:li, class: active_level_for(user_membership, notification_level)) do
+ link_to '#', class: 'update-notification', data: { notification_level: notification_level } do
+ icon("#{icon} fw", text: title)
+ end
+ end
+ end
+
def notification_label(user_membership)
Notification.new(user_membership).to_s
end
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index 4710171ebaa..c73cb3028ee 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -34,7 +34,8 @@ module PreferencesHelper
def project_view_choices
[
['Readme (default)', :readme],
- ['Activity view', :activity]
+ ['Activity view', :activity],
+ ['Files view', :files]
]
end
@@ -46,8 +47,7 @@ module PreferencesHelper
Gitlab::ColorSchemes.for_user(current_user).css_class
end
- def prefer_readme?
- !current_user ||
- current_user.project_view == 'readme'
+ def default_project_view
+ current_user ? current_user.project_view : 'readme'
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index dbadbb74549..690ae2090db 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -70,6 +70,10 @@ module ProjectsHelper
"You are going to transfer #{project.name_with_namespace} to another owner. Are you ABSOLUTELY sure?"
end
+ def remove_fork_project_message(project)
+ "You are going to remove the fork relationship to source project #{@project.forked_from_project.name_with_namespace}. Are you ABSOLUTELY sure?"
+ end
+
def project_nav_tabs
@nav_tabs ||= get_project_nav_tabs(@project, current_user)
end
@@ -113,7 +117,7 @@ module ProjectsHelper
nav_tabs << :merge_requests
end
- if can?(current_user, :read_build, project)
+ if project.builds_enabled? && can?(current_user, :read_build, project)
nav_tabs << :builds
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index c31a556ff7b..a6ee6880247 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -70,7 +70,7 @@ module SearchHelper
# Autocomplete results for the current user's groups
def groups_autocomplete(term, limit = 5)
- current_user.authorized_groups.search(term).limit(limit).map do |group|
+ GroupsFinder.new.execute(current_user).search(term).limit(limit).map do |group|
{
label: "group: #{search_result_sanitize(group.name)}",
url: group_path(group)
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index 0e7d8065ac7..04e53fe7c61 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -110,22 +110,4 @@ module TabHelper
'active'
end
end
-
- # Use nav_tab for save controller/action but different params
- def nav_tab(key, value, &block)
- o = {}
- o[:class] = ""
-
- if value.nil?
- o[:class] << " active" if params[key].blank?
- else
- o[:class] << " active" if params[key] == value
- end
-
- if block_given?
- content_tag(:li, capture(&block), o)
- else
- content_tag(:li, nil, o)
- end
- end
end
diff --git a/app/mailers/abuse_report_mailer.rb b/app/mailers/abuse_report_mailer.rb
new file mode 100644
index 00000000000..f0c41f69a5c
--- /dev/null
+++ b/app/mailers/abuse_report_mailer.rb
@@ -0,0 +1,12 @@
+class AbuseReportMailer < BaseMailer
+ include Gitlab::CurrentSettings
+
+ def notify(abuse_report_id)
+ @abuse_report = AbuseReport.find(abuse_report_id)
+
+ mail(
+ to: current_application_settings.admin_notification_email,
+ subject: "#{@abuse_report.user.name} (#{@abuse_report.user.username}) was reported for abuse"
+ )
+ end
+end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 38bc2086683..d01b3ae6f05 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -154,6 +154,7 @@ class Ability
:create_merge_request,
:create_wiki,
:manage_builds,
+ :download_build_artifacts,
:push_code
]
end
@@ -189,7 +190,8 @@ class Ability
:change_visibility_level,
:rename_project,
:remove_project,
- :archive_project
+ :archive_project,
+ :remove_fork_project
]
end
@@ -231,6 +233,7 @@ class Ability
if group.has_master?(user) || group.has_owner?(user) || user.admin?
rules.push(*[
:create_projects,
+ :admin_milestones
])
end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index c8841178e93..9e70247ef51 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -23,6 +23,10 @@
# after_sign_out_path :string(255)
# session_expire_delay :integer default(10080), not null
# import_sources :text
+# help_page_text :text
+# admin_notification_email :string(255)
+# shared_runners_enabled :boolean default(TRUE), not null
+# max_artifacts_size :integer default(100), not null
#
class ApplicationSetting < ActiveRecord::Base
@@ -44,6 +48,10 @@ class ApplicationSetting < ActiveRecord::Base
allow_blank: true,
format: { with: /\A#{URI.regexp(%w(http https))}\z/, message: "should be a valid url" }
+ validates :admin_notification_email,
+ allow_blank: true,
+ email: true
+
validates_each :restricted_visibility_levels do |record, attr, value|
unless value.nil?
value.each do |level|
@@ -64,8 +72,14 @@ class ApplicationSetting < ActiveRecord::Base
end
end
+ after_commit do
+ Rails.cache.write('application_setting.last', self)
+ end
+
def self.current
- ApplicationSetting.last
+ Rails.cache.fetch('application_setting.last') do
+ ApplicationSetting.last
+ end
end
def self.create_from_defaults
@@ -83,7 +97,9 @@ class ApplicationSetting < ActiveRecord::Base
default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'],
restricted_signup_domains: Settings.gitlab['restricted_signup_domains'],
- import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git']
+ import_sources: ['github','bitbucket','gitlab','gitorious','google_code','fogbugz','git'],
+ shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
+ max_artifacts_size: Settings.gitlab_ci['max_artifacts_size'],
)
end
diff --git a/app/models/ci/application_setting.rb b/app/models/ci/application_setting.rb
index 0cf496f7d81..1307fa0b472 100644
--- a/app/models/ci/application_setting.rb
+++ b/app/models/ci/application_setting.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: application_settings
+# Table name: ci_application_settings
#
# id :integer not null, primary key
# all_broken_builds :boolean
@@ -12,9 +12,15 @@
module Ci
class ApplicationSetting < ActiveRecord::Base
extend Ci::Model
-
+
+ after_commit do
+ Rails.cache.write('ci_application_setting.last', self)
+ end
+
def self.current
- Ci::ApplicationSetting.last
+ Rails.cache.fetch('ci_application_setting.last') do
+ Ci::ApplicationSetting.last
+ end
end
def self.create_from_defaults
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 5f8d44148ca..e78b154084b 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: builds
+# Table name: ci_builds
#
# id :integer not null, primary key
# project_id :integer
@@ -11,16 +11,24 @@
# updated_at :datetime
# started_at :datetime
# runner_id :integer
-# commit_id :integer
# coverage :float
+# commit_id :integer
# commands :text
# job_id :integer
# name :string(255)
+# deploy :boolean default(FALSE)
# options :text
# allow_failure :boolean default(FALSE), not null
# stage :string(255)
-# deploy :boolean default(FALSE)
# trigger_request_id :integer
+# stage_idx :integer
+# tag :boolean
+# ref :string(255)
+# user_id :integer
+# type :string(255)
+# target_url :string(255)
+# description :string(255)
+# artifacts_file :text
#
module Ci
@@ -39,6 +47,8 @@ module Ci
scope :ignore_failures, ->() { where(allow_failure: false) }
scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) }
+ mount_uploader :artifacts_file, ArtifactUploader
+
acts_as_taggable
# To prevent db load megabytes of data from trace
@@ -93,10 +103,7 @@ module Ci
Ci::WebHookService.new.build_end(build)
end
- if build.commit.should_create_next_builds?(build)
- build.commit.create_next_builds(build.ref, build.tag, build.user, build.trigger_request)
- end
-
+ build.commit.create_next_builds(build)
project.execute_services(build)
if project.coverage_enabled?
@@ -109,6 +116,14 @@ module Ci
failed? && allow_failure?
end
+ def retryable?
+ commands.present?
+ end
+
+ def retried?
+ !self.commit.latest_builds_for_ref(self.ref).include?(self)
+ end
+
def trace_html
html = Ci::Ansi2html::convert(trace) if trace.present?
html || ''
@@ -212,6 +227,14 @@ module Ci
"#{dir_to_trace}/#{id}.log"
end
+ def token
+ project.token
+ end
+
+ def valid_token? token
+ project.valid_token? token
+ end
+
def target_url
Gitlab::Application.routes.url_helpers.
namespace_project_build_url(gl_project.namespace, gl_project, self)
@@ -225,7 +248,7 @@ module Ci
end
def retry_url
- if commands.present?
+ if retryable?
Gitlab::Application.routes.url_helpers.
retry_namespace_project_build_path(gl_project.namespace, gl_project, self)
end
@@ -243,6 +266,13 @@ module Ci
pending? && !any_runners_online?
end
+ def download_url
+ if artifacts_file.exists?
+ Gitlab::Application.routes.url_helpers.
+ download_namespace_project_build_path(gl_project.namespace, gl_project, self)
+ end
+ end
+
private
def yaml_variables
diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb
index cd45366b34e..33b57173928 100644
--- a/app/models/ci/commit.rb
+++ b/app/models/ci/commit.rb
@@ -1,18 +1,19 @@
# == Schema Information
#
-# Table name: commits
+# Table name: ci_commits
#
-# id :integer not null, primary key
-# project_id :integer
-# ref :string(255)
-# sha :string(255)
-# before_sha :string(255)
-# push_data :text
-# created_at :datetime
-# updated_at :datetime
-# tag :boolean default(FALSE)
-# yaml_errors :text
-# committed_at :datetime
+# id :integer not null, primary key
+# project_id :integer
+# ref :string(255)
+# sha :string(255)
+# before_sha :string(255)
+# push_data :text
+# created_at :datetime
+# updated_at :datetime
+# tag :boolean default(FALSE)
+# yaml_errors :text
+# committed_at :datetime
+# gl_project_id :integer
#
module Ci
@@ -91,19 +92,28 @@ module Ci
def create_builds(ref, tag, user, trigger_request = nil)
return unless config_processor
config_processor.stages.any? do |stage|
- CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present?
+ CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request, 'success').present?
end
end
- def create_next_builds(ref, tag, user, trigger_request)
+ def create_next_builds(build)
return unless config_processor
- stages = builds.where(ref: ref, tag: tag, trigger_request: trigger_request).group_by(&:stage)
+ # don't create other builds if this one is retried
+ latest_builds = builds.similar(build).latest
+ return unless latest_builds.exists?(build.id)
- config_processor.stages.any? do |stage|
- unless stages.include?(stage)
- CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request).present?
- end
+ # get list of stages after this build
+ next_stages = config_processor.stages.drop_while { |stage| stage != build.stage }
+ next_stages.delete(build.stage)
+
+ # get status for all prior builds
+ prior_builds = latest_builds.reject { |other_build| next_stages.include?(other_build.stage) }
+ status = Ci::Status.get_status(prior_builds)
+
+ # create builds for next stages based
+ next_stages.any? do |stage|
+ CreateBuildsService.new.execute(self, stage, build.ref, build.tag, build.user, build.trigger_request, status).present?
end
end
@@ -132,24 +142,7 @@ module Ci
return 'failed'
end
- @status ||= begin
- latest = latest_statuses
- latest.reject! { |status| status.try(&:allow_failure?) }
-
- if latest.none?
- 'skipped'
- elsif latest.all?(&:success?)
- 'success'
- elsif latest.all?(&:pending?)
- 'pending'
- elsif latest.any?(&:running?) || latest.any?(&:pending?)
- 'running'
- elsif latest.all?(&:canceled?)
- 'canceled'
- else
- 'failed'
- end
- end
+ @status ||= Ci::Status.get_status(latest_statuses)
end
def pending?
@@ -195,7 +188,7 @@ module Ci
end
def config_processor
- @config_processor ||= Ci::GitlabCiYamlProcessor.new(ci_yaml_file)
+ @config_processor ||= Ci::GitlabCiYamlProcessor.new(ci_yaml_file, gl_project.path_with_namespace)
rescue Ci::GitlabCiYamlProcessor::ValidationError => e
save_yaml_error(e.message)
nil
@@ -219,16 +212,6 @@ module Ci
update!(committed_at: DateTime.now)
end
- def should_create_next_builds?(build)
- # don't create other builds if this one is retried
- other_builds = builds.similar(build).latest
- return false unless other_builds.include?(build)
-
- other_builds.all? do |build|
- build.success? || build.ignored?
- end
- end
-
private
def save_yaml_error(error)
diff --git a/app/models/ci/event.rb b/app/models/ci/event.rb
index cac3a7a49c1..8c39be42677 100644
--- a/app/models/ci/event.rb
+++ b/app/models/ci/event.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: events
+# Table name: ci_events
#
# id :integer not null, primary key
# project_id :integer
diff --git a/app/models/ci/project.rb b/app/models/ci/project.rb
index eb65c773570..669ee1cc0d2 100644
--- a/app/models/ci/project.rb
+++ b/app/models/ci/project.rb
@@ -1,9 +1,9 @@
# == Schema Information
#
-# Table name: projects
+# Table name: ci_projects
#
# id :integer not null, primary key
-# name :string(255) not null
+# name :string(255)
# timeout :integer default(3600), not null
# created_at :datetime
# updated_at :datetime
@@ -66,30 +66,6 @@ module Ci
class << self
include Ci::CurrentSettings
- def base_build_script
- <<-eos
- git submodule update --init
- ls -la
- eos
- end
-
- def parse(project)
- params = {
- gitlab_id: project.id,
- default_ref: project.default_branch || 'master',
- email_add_pusher: current_application_settings.add_pusher,
- email_only_broken_builds: current_application_settings.all_broken_builds,
- }
-
- project = Ci::Project.new(params)
- project.build_missing_services
- project
- end
-
- def already_added?(project)
- where(gitlab_id: project.id).any?
- end
-
def unassigned(runner)
joins("LEFT JOIN #{Ci::RunnerProject.table_name} ON #{Ci::RunnerProject.table_name}.project_id = #{Ci::Project.table_name}.id " \
"AND #{Ci::RunnerProject.table_name}.runner_id = #{runner.id}").
@@ -99,6 +75,7 @@ module Ci
def ordered_by_last_commit_date
last_commit_subquery = "(SELECT gl_project_id, MAX(committed_at) committed_at FROM #{Ci::Commit.table_name} GROUP BY gl_project_id)"
joins("LEFT JOIN #{last_commit_subquery} AS last_commit ON #{Ci::Project.table_name}.gitlab_id = last_commit.gl_project_id").
+ joins(:gl_project).
order("CASE WHEN last_commit.committed_at IS NULL THEN 1 ELSE 0 END, last_commit.committed_at DESC")
end
end
diff --git a/app/models/ci/project_status.rb b/app/models/ci/project_status.rb
index b66f1212f23..2d35aeac225 100644
--- a/app/models/ci/project_status.rb
+++ b/app/models/ci/project_status.rb
@@ -27,9 +27,5 @@ module Ci
def human_status
status
end
-
- def last_commit_for_ref(ref)
- commits.where(ref: ref).last
- end
end
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 1b3669f1b7a..89710485811 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: runners
+# Table name: ci_runners
#
# id :integer not null, primary key
# token :string(255)
@@ -36,6 +36,7 @@ module Ci
scope :active, ->() { where(active: true) }
scope :paused, ->() { where(active: false) }
scope :online, ->() { where('contacted_at > ?', LAST_CONTACT_TIME) }
+ scope :ordered, ->() { order(id: :desc) }
acts_as_taggable
diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb
index 44453ee4b41..3f4fc43873e 100644
--- a/app/models/ci/runner_project.rb
+++ b/app/models/ci/runner_project.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: runner_projects
+# Table name: ci_runner_projects
#
# id :integer not null, primary key
# runner_id :integer not null
diff --git a/app/models/ci/service.rb b/app/models/ci/service.rb
index ed5e3f940b6..8063c51e82b 100644
--- a/app/models/ci/service.rb
+++ b/app/models/ci/service.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: services
+# Table name: ci_services
#
# id :integer not null, primary key
# type :string(255)
diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb
index fe224b7dc70..b73c35d5ae5 100644
--- a/app/models/ci/trigger.rb
+++ b/app/models/ci/trigger.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: triggers
+# Table name: ci_triggers
#
# id :integer not null, primary key
# token :string(255)
diff --git a/app/models/ci/trigger_request.rb b/app/models/ci/trigger_request.rb
index 29cd9553394..9973d2e5ade 100644
--- a/app/models/ci/trigger_request.rb
+++ b/app/models/ci/trigger_request.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: trigger_requests
+# Table name: ci_trigger_requests
#
# id :integer not null, primary key
# trigger_id :integer not null
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index 7a542802fa6..b3d2b809e03 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: variables
+# Table name: ci_variables
#
# id :integer not null, primary key
# project_id :integer not null
diff --git a/app/models/ci/web_hook.rb b/app/models/ci/web_hook.rb
index 8f03b0625da..7ca16a1bde8 100644
--- a/app/models/ci/web_hook.rb
+++ b/app/models/ci/web_hook.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: web_hooks
+# Table name: ci_web_hooks
#
# id :integer not null, primary key
# url :string(255) not null
diff --git a/app/models/commit.rb b/app/models/commit.rb
index d5c50013525..492f6be1ce3 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -2,13 +2,13 @@ class Commit
extend ActiveModel::Naming
include ActiveModel::Conversion
- include Mentionable
include Participable
+ include Mentionable
include Referable
include StaticModel
attr_mentionable :safe_message
- participant :author, :committer, :notes, :mentioned_users
+ participant :author, :committer, :notes
attr_accessor :project
@@ -164,6 +164,14 @@ class Commit
@committer ||= User.find_by_any_email(committer_email)
end
+ def parents
+ @parents ||= parent_ids.map { |id| project.commit(id) }
+ end
+
+ def parent
+ @parent ||= project.commit(self.parent_id) if self.parent_id
+ end
+
def notes
project.notes.for_commit_id(self.id)
end
@@ -181,10 +189,6 @@ class Commit
@raw.short_id(7)
end
- def parents
- @parents ||= Commit.decorate(super, project)
- end
-
def ci_commit
project.ci_commit(sha)
end
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 0b71838d515..e70f4d37184 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -1,3 +1,36 @@
+# == Schema Information
+#
+# Table name: ci_builds
+#
+# id :integer not null, primary key
+# project_id :integer
+# status :string(255)
+# finished_at :datetime
+# trace :text
+# created_at :datetime
+# updated_at :datetime
+# started_at :datetime
+# runner_id :integer
+# coverage :float
+# commit_id :integer
+# commands :text
+# job_id :integer
+# name :string(255)
+# deploy :boolean default(FALSE)
+# options :text
+# allow_failure :boolean default(FALSE), not null
+# stage :string(255)
+# trigger_request_id :integer
+# stage_idx :integer
+# tag :boolean
+# ref :string(255)
+# user_id :integer
+# type :string(255)
+# target_url :string(255)
+# description :string(255)
+# artifacts_file :text
+#
+
class CommitStatus < ActiveRecord::Base
self.table_name = 'ci_builds'
@@ -15,12 +48,11 @@ class CommitStatus < ActiveRecord::Base
scope :pending, -> { where(status: 'pending') }
scope :success, -> { where(status: 'success') }
scope :failed, -> { where(status: 'failed') }
- scope :running_or_pending, -> { where(status:[:running, :pending]) }
- scope :finished, -> { where(status:[:success, :failed, :canceled]) }
+ scope :running_or_pending, -> { where(status: [:running, :pending]) }
+ scope :finished, -> { where(status: [:success, :failed, :canceled]) }
scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :ref)) }
scope :ordered, -> { order(:ref, :stage_idx, :name) }
scope :for_ref, ->(ref) { where(ref: ref) }
- scope :running_or_pending, -> { where(status: [:running, :pending]) }
state_machine :status, initial: :pending do
event :run do
@@ -28,7 +60,7 @@ class CommitStatus < ActiveRecord::Base
end
event :drop do
- transition running: :failed
+ transition [:pending, :running] => :failed
end
event :success do
@@ -93,4 +125,8 @@ class CommitStatus < ActiveRecord::Base
def show_warning?
false
end
+
+ def download_url
+ nil
+ end
end
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 0e8bcc1a4ec..492a026add9 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -6,8 +6,8 @@
#
module Issuable
extend ActiveSupport::Concern
- include Mentionable
include Participable
+ include Mentionable
included do
belongs_to :author, class_name: "User"
@@ -24,7 +24,7 @@ module Issuable
scope :authored, ->(user) { where(author_id: user) }
scope :assigned_to, ->(u) { where(assignee_id: u.id)}
- scope :recent, -> { order("created_at DESC") }
+ scope :recent, -> { reorder(id: :desc) }
scope :assigned, -> { where("assignee_id IS NOT NULL") }
scope :unassigned, -> { where("assignee_id IS NULL") }
scope :of_projects, ->(ids) { where(project_id: ids) }
@@ -47,8 +47,7 @@ module Issuable
prefix: true
attr_mentionable :title, :description
-
- participant :author, :assignee, :notes_with_associations, :mentioned_users
+ participant :author, :assignee, :notes_with_associations
end
module ClassMethods
@@ -86,6 +85,10 @@ module Issuable
assignee_id_changed?
end
+ def open?
+ opened? || reopened?
+ end
+
#
# Votes
#
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index b34def66d2e..193c91f1742 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -20,6 +20,12 @@ module Mentionable
end
end
+ included do
+ if self < Participable
+ participant ->(current_user) { mentioned_users(current_user, load_lazy_references: false) }
+ end
+ end
+
# Returns the text used as the body of a Note when this object is referenced
#
# By default this will be the class name and the result of calling
@@ -41,22 +47,22 @@ module Mentionable
self
end
- def all_references(current_user = self.author, text = self.mentionable_text)
- ext = Gitlab::ReferenceExtractor.new(self.project, current_user)
+ def all_references(current_user = self.author, text = self.mentionable_text, load_lazy_references: true)
+ ext = Gitlab::ReferenceExtractor.new(self.project, current_user, load_lazy_references: load_lazy_references)
ext.analyze(text)
ext
end
- def mentioned_users(current_user = nil)
- all_references(current_user).users.uniq
+ def mentioned_users(current_user = nil, load_lazy_references: true)
+ all_references(current_user, load_lazy_references: load_lazy_references).users
end
# Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference.
- def referenced_mentionables(current_user = self.author, text = self.mentionable_text)
+ def referenced_mentionables(current_user = self.author, text = self.mentionable_text, load_lazy_references: true)
return [] if text.blank?
- refs = all_references(current_user, text)
- (refs.issues + refs.merge_requests + refs.commits).uniq - [local_reference]
+ refs = all_references(current_user, text, load_lazy_references: load_lazy_references)
+ (refs.issues + refs.merge_requests + refs.commits) - [local_reference]
end
# Create a cross-reference Note for each GFM reference to another Mentionable found in +mentionable_text+.
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index ffc874357fd..85367f89f4f 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -12,7 +12,7 @@
#
# # ...
#
-# participant :author, :assignee, :mentioned_users, :notes
+# participant :author, :assignee, :notes, ->(current_user) { mentioned_users(current_user) }
# end
#
# issue = Issue.last
@@ -27,7 +27,7 @@ module Participable
module ClassMethods
def participant(*attrs)
- participant_attrs.concat(attrs.map(&:to_s))
+ participant_attrs.concat(attrs)
end
def participant_attrs
@@ -37,33 +37,39 @@ module Participable
# Be aware that this method makes a lot of sql queries.
# Save result into variable if you are going to reuse it inside same request
- def participants(current_user = self.author)
- self.class.participant_attrs.flat_map do |attr|
- meth = method(attr)
-
+ def participants(current_user = self.author, load_lazy_references: true)
+ participants = self.class.participant_attrs.flat_map do |attr|
value =
- if meth.arity == 1 || meth.arity == -1
- meth.call(current_user)
+ if attr.respond_to?(:call)
+ instance_exec(current_user, &attr)
else
- meth.call
+ send(attr)
end
participants_for(value, current_user)
- end.compact.uniq.select do |user|
- user.can?(:read_project, self.project)
+ end.compact.uniq
+
+ if load_lazy_references
+ participants = Gitlab::Markdown::ReferenceFilter::LazyReference.load(participants).uniq
+
+ participants.select! do |user|
+ user.can?(:read_project, project)
+ end
end
+
+ participants
end
private
def participants_for(value, current_user = nil)
case value
- when User
+ when User, Gitlab::Markdown::ReferenceFilter::LazyReference
[value]
when Enumerable, ActiveRecord::Relation
value.flat_map { |v| participants_for(v, current_user) }
when Participable
- value.participants(current_user)
+ value.participants(current_user, load_lazy_references: false)
end
end
end
diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb
index 0ad2654867d..913c747a1c3 100644
--- a/app/models/concerns/sortable.rb
+++ b/app/models/concerns/sortable.rb
@@ -8,12 +8,12 @@ module Sortable
included do
# By default all models should be ordered
# by created_at field starting from newest
- default_scope { order(created_at: :desc, id: :desc) }
+ default_scope { order(id: :desc) }
- scope :order_created_desc, -> { reorder(created_at: :desc, id: :desc) }
- scope :order_created_asc, -> { reorder(created_at: :asc, id: :asc) }
- scope :order_updated_desc, -> { reorder(updated_at: :desc, id: :desc) }
- scope :order_updated_asc, -> { reorder(updated_at: :asc, id: :asc) }
+ scope :order_created_desc, -> { reorder(created_at: :desc) }
+ scope :order_created_asc, -> { reorder(created_at: :asc) }
+ scope :order_updated_desc, -> { reorder(updated_at: :desc) }
+ scope :order_updated_asc, -> { reorder(updated_at: :asc) }
scope :order_name_asc, -> { reorder(name: :asc) }
scope :order_name_desc, -> { reorder(name: :desc) }
end
diff --git a/app/models/event.rb b/app/models/event.rb
index 47600c57e35..bf64ac29d32 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -45,7 +45,7 @@ class Event < ActiveRecord::Base
after_create :reset_project_activity
# Scopes
- scope :recent, -> { order(created_at: :desc) }
+ scope :recent, -> { reorder(id: :desc) }
scope :code_push, -> { where(action: PUSHED) }
scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent }
scope :with_associations, -> { includes(project: :namespace) }
diff --git a/app/models/generic_commit_status.rb b/app/models/generic_commit_status.rb
index fa54e3540d0..12c934e2494 100644
--- a/app/models/generic_commit_status.rb
+++ b/app/models/generic_commit_status.rb
@@ -1,3 +1,36 @@
+# == Schema Information
+#
+# Table name: ci_builds
+#
+# id :integer not null, primary key
+# project_id :integer
+# status :string(255)
+# finished_at :datetime
+# trace :text
+# created_at :datetime
+# updated_at :datetime
+# started_at :datetime
+# runner_id :integer
+# coverage :float
+# commit_id :integer
+# commands :text
+# job_id :integer
+# name :string(255)
+# deploy :boolean default(FALSE)
+# options :text
+# allow_failure :boolean default(FALSE), not null
+# stage :string(255)
+# trigger_request_id :integer
+# stage_idx :integer
+# tag :boolean
+# ref :string(255)
+# user_id :integer
+# type :string(255)
+# target_url :string(255)
+# description :string(255)
+# artifacts_file :text
+#
+
class GenericCommitStatus < CommitStatus
before_validation :set_default_values
diff --git a/app/models/global_label.rb b/app/models/global_label.rb
new file mode 100644
index 00000000000..0171f7d54b7
--- /dev/null
+++ b/app/models/global_label.rb
@@ -0,0 +1,17 @@
+class GlobalLabel
+ attr_accessor :title, :labels
+ alias_attribute :name, :title
+
+ def self.build_collection(labels)
+ labels = labels.group_by(&:title)
+
+ labels.map do |title, label|
+ new(title, label)
+ end
+ end
+
+ def initialize(title, labels)
+ @title = title
+ @labels = labels
+ end
+end
diff --git a/app/models/group_milestone.rb b/app/models/global_milestone.rb
index 1dd2be68ebf..1321ccd963f 100644
--- a/app/models/group_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -1,24 +1,24 @@
-class GroupMilestone
-
+class GlobalMilestone
+ attr_accessor :title, :milestones
alias_attribute :name, :title
+ def self.build_collection(milestones)
+ milestones = milestones.group_by(&:title)
+
+ milestones.map do |title, milestones|
+ new(title, milestones)
+ end
+ end
+
def initialize(title, milestones)
@title = title
@milestones = milestones
end
- def title
- @title
- end
-
def safe_title
@title.parameterize
end
- def milestones
- @milestones
- end
-
def projects
milestones.map { |milestone| milestone.project }
end
@@ -68,15 +68,15 @@ class GroupMilestone
end
def issues
- @group_issues ||= milestones.map(&:issues).flatten.group_by(&:state)
+ @issues ||= milestones.map(&:issues).flatten.group_by(&:state)
end
def merge_requests
- @group_merge_requests ||= milestones.map(&:merge_requests).flatten.group_by(&:state)
+ @merge_requests ||= milestones.map(&:merge_requests).flatten.group_by(&:state)
end
def participants
- @group_participants ||= milestones.map(&:participants).flatten.compact.uniq
+ @participants ||= milestones.map(&:participants).flatten.compact.uniq
end
def opened_issues
@@ -94,4 +94,8 @@ class GroupMilestone
def closed_merge_requests
merge_requests.values_at("closed", "merged", "locked").compact.flatten
end
+
+ def complete?
+ total_items_count == closed_items_count
+ end
end
diff --git a/app/models/group.rb b/app/models/group.rb
index 465c22d23ac..793a3b5ef2e 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -11,6 +11,7 @@
# type :string(255)
# description :string(255) default(""), not null
# avatar :string(255)
+# public :boolean default(FALSE)
#
require 'carrierwave/orm/activerecord'
@@ -120,7 +121,7 @@ class Group < Namespace
end
def public_profile?
- projects.public_only.any?
+ self.public || projects.public_only.any?
end
def post_create_hook
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index ca7066b959a..337b3097126 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -2,18 +2,19 @@
#
# Table name: web_hooks
#
-# id :integer not null, primary key
-# url :string(255)
-# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# type :string(255) default("ProjectHook")
-# service_id :integer
-# push_events :boolean default(TRUE), not null
-# issues_events :boolean default(FALSE), not null
-# merge_requests_events :boolean default(FALSE), not null
-# tag_push_events :boolean default(FALSE)
-# note_events :boolean default(FALSE), not null
+# id :integer not null, primary key
+# url :string(255)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string(255) default("ProjectHook")
+# service_id :integer
+# push_events :boolean default(TRUE), not null
+# issues_events :boolean default(FALSE), not null
+# merge_requests_events :boolean default(FALSE), not null
+# tag_push_events :boolean default(FALSE)
+# note_events :boolean default(FALSE), not null
+# enable_ssl_verification :boolean default(TRUE)
#
class ProjectHook < WebHook
diff --git a/app/models/hooks/service_hook.rb b/app/models/hooks/service_hook.rb
index b55e217975f..09bb3ee52a2 100644
--- a/app/models/hooks/service_hook.rb
+++ b/app/models/hooks/service_hook.rb
@@ -2,18 +2,19 @@
#
# Table name: web_hooks
#
-# id :integer not null, primary key
-# url :string(255)
-# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# type :string(255) default("ProjectHook")
-# service_id :integer
-# push_events :boolean default(TRUE), not null
-# issues_events :boolean default(FALSE), not null
-# merge_requests_events :boolean default(FALSE), not null
-# tag_push_events :boolean default(FALSE)
-# note_events :boolean default(FALSE), not null
+# id :integer not null, primary key
+# url :string(255)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string(255) default("ProjectHook")
+# service_id :integer
+# push_events :boolean default(TRUE), not null
+# issues_events :boolean default(FALSE), not null
+# merge_requests_events :boolean default(FALSE), not null
+# tag_push_events :boolean default(FALSE)
+# note_events :boolean default(FALSE), not null
+# enable_ssl_verification :boolean default(TRUE)
#
class ServiceHook < WebHook
diff --git a/app/models/hooks/system_hook.rb b/app/models/hooks/system_hook.rb
index 6fb2d421026..2f63c59b07e 100644
--- a/app/models/hooks/system_hook.rb
+++ b/app/models/hooks/system_hook.rb
@@ -2,18 +2,19 @@
#
# Table name: web_hooks
#
-# id :integer not null, primary key
-# url :string(255)
-# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# type :string(255) default("ProjectHook")
-# service_id :integer
-# push_events :boolean default(TRUE), not null
-# issues_events :boolean default(FALSE), not null
-# merge_requests_events :boolean default(FALSE), not null
-# tag_push_events :boolean default(FALSE)
-# note_events :boolean default(FALSE), not null
+# id :integer not null, primary key
+# url :string(255)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string(255) default("ProjectHook")
+# service_id :integer
+# push_events :boolean default(TRUE), not null
+# issues_events :boolean default(FALSE), not null
+# merge_requests_events :boolean default(FALSE), not null
+# tag_push_events :boolean default(FALSE)
+# note_events :boolean default(FALSE), not null
+# enable_ssl_verification :boolean default(TRUE)
#
class SystemHook < WebHook
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index a078accbdbd..d6c6f415c4a 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -2,18 +2,19 @@
#
# Table name: web_hooks
#
-# id :integer not null, primary key
-# url :string(255)
-# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# type :string(255) default("ProjectHook")
-# service_id :integer
-# push_events :boolean default(TRUE), not null
-# issues_events :boolean default(FALSE), not null
-# merge_requests_events :boolean default(FALSE), not null
-# tag_push_events :boolean default(FALSE)
-# note_events :boolean default(FALSE), not null
+# id :integer not null, primary key
+# url :string(255)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string(255) default("ProjectHook")
+# service_id :integer
+# push_events :boolean default(TRUE), not null
+# issues_events :boolean default(FALSE), not null
+# merge_requests_events :boolean default(FALSE), not null
+# tag_push_events :boolean default(FALSE)
+# note_events :boolean default(FALSE), not null
+# enable_ssl_verification :boolean default(TRUE)
#
class WebHook < ActiveRecord::Base
diff --git a/app/models/issue.rb b/app/models/issue.rb
index fc7e9abe29e..72183108033 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -95,4 +95,14 @@ class Issue < ActiveRecord::Base
def source_project
project
end
+
+ # From all notes on this issue, we'll select the system notes about linked
+ # merge requests. Of those, the MRs closing `self` are returned.
+ def closed_by_merge_requests(current_user = nil)
+ return [] unless open?
+
+ notes.system.flat_map do |note|
+ note.all_references(current_user).merge_requests
+ end.uniq.select { |mr| mr.open? && mr.closes_issue?(self) }
+ end
end
diff --git a/app/models/label.rb b/app/models/label.rb
index 1bb4b5f55cf..b306aecbac1 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -8,6 +8,7 @@
# project_id :integer
# created_at :datetime
# updated_at :datetime
+# template :boolean default(FALSE)
#
class Label < ActiveRecord::Base
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
new file mode 100644
index 00000000000..3c1426f59d0
--- /dev/null
+++ b/app/models/lfs_object.rb
@@ -0,0 +1,8 @@
+class LfsObject < ActiveRecord::Base
+ has_many :lfs_objects_projects, dependent: :destroy
+ has_many :projects, through: :lfs_objects_projects
+
+ validates :oid, presence: true, uniqueness: true
+
+ mount_uploader :file, LfsObjectUploader
+end
diff --git a/app/models/lfs_objects_project.rb b/app/models/lfs_objects_project.rb
new file mode 100644
index 00000000000..0fd5f089db9
--- /dev/null
+++ b/app/models/lfs_objects_project.rb
@@ -0,0 +1,8 @@
+class LfsObjectsProject < ActiveRecord::Base
+ belongs_to :project
+ belongs_to :lfs_object
+
+ validates :lfs_object_id, presence: true
+ validates :lfs_object_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
+ validates :project_id, presence: true
+end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index c83b15c7d39..2eb03b8ba5b 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -20,6 +20,7 @@
# position :integer default(0)
# locked_at :datetime
# updated_by_id :integer
+# merge_error :string(255)
#
require Rails.root.join("app/models/commit")
@@ -40,7 +41,7 @@ class MergeRequest < ActiveRecord::Base
after_create :create_merge_request_diff
after_update :update_merge_request_diff
- delegate :commits, :diffs, :last_commit, :last_commit_short_sha, to: :merge_request_diff, prefix: nil
+ delegate :commits, :diffs, :diffs_no_whitespace, to: :merge_request_diff, prefix: nil
# When this attribute is true some MR validation is ignored
# It allows us to close or modify broken merge requests
@@ -157,6 +158,18 @@ class MergeRequest < ActiveRecord::Base
reference
end
+ def last_commit
+ merge_request_diff ? merge_request_diff.last_commit : compare_commits.last
+ end
+
+ def first_commit
+ merge_request_diff ? merge_request_diff.first_commit : compare_commits.first
+ end
+
+ def last_commit_short_sha
+ last_commit.short_id
+ end
+
def validate_branches
if target_project == source_project && target_branch == source_branch
errors.add :branch_conflict, "You can not use same project/branch for source and target"
@@ -222,10 +235,6 @@ class MergeRequest < ActiveRecord::Base
self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
end
- def open?
- opened? || reopened?
- end
-
def work_in_progress?
!!(title =~ /\A\[?WIP\]?:? /i)
end
@@ -249,7 +258,7 @@ class MergeRequest < ActiveRecord::Base
Note.where(
"(project_id = :target_project_id AND noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR" +
- "(project_id = :source_project_id AND noteable_type = 'Commit' AND commit_id IN (:commit_ids))",
+ "((project_id = :source_project_id OR project_id = :target_project_id) AND noteable_type = 'Commit' AND commit_id IN (:commit_ids))",
mr_id: id,
commit_ids: commit_ids,
target_project_id: target_project_id,
@@ -294,6 +303,10 @@ class MergeRequest < ActiveRecord::Base
target_project
end
+ def closes_issue?(issue)
+ closes_issues.include?(issue)
+ end
+
# Return the set of issues that will be closed if this merge request is accepted.
def closes_issues(current_user = self.author)
if target_branch == project.default_branch
@@ -458,4 +471,10 @@ class MergeRequest < ActiveRecord::Base
unlock_mr if locked?
end
end
+
+ def ci_commit
+ if last_commit
+ source_project.ci_commit(last_commit.id)
+ end
+ end
end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index c9ef8023aea..c499a4b5b4c 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -19,7 +19,7 @@ class MergeRequestDiff < ActiveRecord::Base
# Prevent store of diff if commits amount more then 500
COMMITS_SAFE_SIZE = 500
- attr_reader :commits, :diffs
+ attr_reader :commits, :diffs, :diffs_no_whitespace
belongs_to :merge_request
@@ -47,6 +47,20 @@ class MergeRequestDiff < ActiveRecord::Base
@diffs ||= (load_diffs(st_diffs) || [])
end
+ def diffs_no_whitespace
+ # Get latest sha of branch from source project
+ source_sha = merge_request.source_project.commit(source_branch).sha
+
+ compare_result = Gitlab::CompareResult.new(
+ Gitlab::Git::Compare.new(
+ merge_request.target_project.repository.raw_repository,
+ merge_request.target_branch,
+ source_sha,
+ ), { ignore_whitespace_change: true }
+ )
+ @diffs_no_whitespace ||= load_diffs(dump_commits(compare_result.diffs))
+ end
+
def commits
@commits ||= load_commits(st_commits || [])
end
@@ -55,6 +69,10 @@ class MergeRequestDiff < ActiveRecord::Base
commits.first
end
+ def first_commit
+ commits.last
+ end
+
def last_commit_short_sha
@last_commit_short_sha ||= last_commit.short_id
end
@@ -163,7 +181,8 @@ class MergeRequestDiff < ActiveRecord::Base
merge_request.fetch_ref
# Get latest sha of branch from source project
- source_sha = merge_request.source_project.commit(source_branch).sha
+ source_commit = merge_request.source_project.commit(source_branch)
+ source_sha = source_commit.try(:sha)
Gitlab::CompareResult.new(
Gitlab::Git::Compare.new(
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 84acba30b6b..2ff16e2825c 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -105,4 +105,36 @@ class Milestone < ActiveRecord::Base
def author_id
nil
end
+
+ # Sorts the issues for the given IDs.
+ #
+ # This method runs a single SQL query using a CASE statement to update the
+ # position of all issues in the current milestone (scoped to the list of IDs).
+ #
+ # Given the ids [10, 20, 30] this method produces a SQL query something like
+ # the following:
+ #
+ # UPDATE issues
+ # SET position = CASE
+ # WHEN id = 10 THEN 1
+ # WHEN id = 20 THEN 2
+ # WHEN id = 30 THEN 3
+ # ELSE position
+ # END
+ # WHERE id IN (10, 20, 30);
+ #
+ # This method expects that the IDs given in `ids` are already Fixnums.
+ def sort_issues(ids)
+ pairs = []
+
+ ids.each_with_index do |id, index|
+ pairs << id
+ pairs << index + 1
+ end
+
+ conditions = 'WHEN id = ? THEN ? ' * ids.length
+
+ issues.where(id: ids).
+ update_all(["position = CASE #{conditions} ELSE position END", *pairs])
+ end
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 5782e649f8b..20b92e68d61 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -11,6 +11,7 @@
# type :string(255)
# description :string(255) default(""), not null
# avatar :string(255)
+# public :boolean default(FALSE)
#
class Namespace < ActiveRecord::Base
diff --git a/app/models/note.rb b/app/models/note.rb
index ebbdd2f33a1..0b3aa30abd7 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -22,14 +22,14 @@ require 'carrierwave/orm/activerecord'
require 'file_size_validator'
class Note < ActiveRecord::Base
- include Mentionable
include Gitlab::CurrentSettings
include Participable
+ include Mentionable
default_value_for :system, false
attr_mentionable :note
- participant :author, :mentioned_users
+ participant :author
belongs_to :project
belongs_to :noteable, polymorphic: true
diff --git a/app/models/project.rb b/app/models/project.rb
index 88cd88dcb5a..9ea0d15497a 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -37,6 +37,7 @@ class Project < ActiveRecord::Base
include Gitlab::ConfigHelper
include Gitlab::ShellAdapter
include Gitlab::VisibilityLevel
+ include Gitlab::CurrentSettings
include Referable
include Sortable
include AfterCommitQueue
@@ -51,6 +52,7 @@ class Project < ActiveRecord::Base
default_value_for :visibility_level, gitlab_config_features.visibility_level
default_value_for :issues_enabled, gitlab_config_features.issues
default_value_for :merge_requests_enabled, gitlab_config_features.merge_requests
+ default_value_for :builds_enabled, gitlab_config_features.builds
default_value_for :wiki_enabled, gitlab_config_features.wiki
default_value_for :wall_enabled, false
default_value_for :snippets_enabled, gitlab_config_features.snippets
@@ -121,6 +123,9 @@ class Project < ActiveRecord::Base
has_many :starrers, through: :users_star_projects, source: :user
has_many :ci_commits, dependent: :destroy, class_name: 'Ci::Commit', foreign_key: :gl_project_id
has_many :ci_builds, through: :ci_commits, source: :builds, dependent: :destroy, class_name: 'Ci::Build'
+ has_many :releases, dependent: :destroy
+ has_many :lfs_objects_projects, dependent: :destroy
+ has_many :lfs_objects, through: :lfs_objects_projects
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
has_one :gitlab_ci_project, dependent: :destroy, class_name: "Ci::Project", foreign_key: :gitlab_id
@@ -243,11 +248,12 @@ class Project < ActiveRecord::Base
# Use of unscoped ensures we're not secretly adding any ORDER BYs, which
# have a negative impact on performance (and aren't needed for this
# query).
- unscoped.
+ projects = unscoped.
joins(:namespace).
- iwhere('namespaces.path' => namespace_path).
- iwhere('projects.path' => project_path).
- take
+ iwhere('namespaces.path' => namespace_path)
+
+ projects.where('projects.path' => project_path).take ||
+ projects.iwhere('projects.path' => project_path).take
end
def visibility_levels
@@ -454,10 +460,6 @@ class Project < ActiveRecord::Base
list.find { |service| service.to_param == name }
end
- def gitlab_ci?
- gitlab_ci_service && gitlab_ci_service.active && gitlab_ci_project.present?
- end
-
def ci_services
services.select { |service| service.category == :ci }
end
@@ -567,7 +569,7 @@ class Project < ActiveRecord::Base
end
def empty_repo?
- !repository.exists? || repository.empty?
+ !repository.exists? || !repository.has_visible_content?
end
def repo
@@ -774,12 +776,38 @@ class Project < ActiveRecord::Base
end
def ensure_gitlab_ci_project
- gitlab_ci_project || create_gitlab_ci_project
+ gitlab_ci_project || create_gitlab_ci_project(
+ shared_runners_enabled: current_application_settings.shared_runners_enabled
+ )
end
- def enable_ci
+ # TODO: this should be migrated to Project table,
+ # the same as issues_enabled
+ def builds_enabled
+ gitlab_ci_service && gitlab_ci_service.active
+ end
+
+ def builds_enabled?
+ builds_enabled
+ end
+
+ def builds_enabled=(value)
service = gitlab_ci_service || create_gitlab_ci_service
- service.active = true
+ service.active = value
service.save
end
+
+ def enable_ci
+ self.builds_enabled = true
+ end
+
+ def unlink_fork
+ if forked?
+ forked_from_project.lfs_objects.find_each do |lfs_object|
+ lfs_object.projects << self
+ end
+
+ forked_project_link.destroy
+ end
+ end
end
diff --git a/app/models/project_services/ci/hip_chat_message.rb b/app/models/project_services/ci/hip_chat_message.rb
index cbf325cc525..d89466b689f 100644
--- a/app/models/project_services/ci/hip_chat_message.rb
+++ b/app/models/project_services/ci/hip_chat_message.rb
@@ -11,7 +11,7 @@ module Ci
def to_s
lines = Array.new
lines.push("<a href=\"#{ci_project_url(project)}\">#{project.name}</a> - ")
- lines.push("<a href=\"#{ci_namespace_project_commit_url(commit.gl_project.namespace, commit.gl_project, commit.sha)}\">Commit ##{commit.id}</a></br>")
+ lines.push("<a href=\"#{builds_namespace_project_commit_url(commit.gl_project.namespace, commit.gl_project, commit.sha)}\">Commit ##{commit.id}</a></br>")
lines.push("#{commit.short_sha} #{commit.git_author_name} - #{commit.git_commit_message}</br>")
lines.push("#{humanized_status(commit_status)} in #{commit.duration} second(s).")
lines.join('')
diff --git a/app/models/project_services/ci/hip_chat_service.rb b/app/models/project_services/ci/hip_chat_service.rb
index f17993d9f3b..0df03890efb 100644
--- a/app/models/project_services/ci/hip_chat_service.rb
+++ b/app/models/project_services/ci/hip_chat_service.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: services
+# Table name: ci_services
#
# id :integer not null, primary key
# type :string(255)
diff --git a/app/models/project_services/ci/mail_service.rb b/app/models/project_services/ci/mail_service.rb
index fd193301001..d31dd6899c1 100644
--- a/app/models/project_services/ci/mail_service.rb
+++ b/app/models/project_services/ci/mail_service.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: services
+# Table name: ci_services
#
# id :integer not null, primary key
# type :string(255)
diff --git a/app/models/project_services/ci/slack_message.rb b/app/models/project_services/ci/slack_message.rb
index dc050a3fc59..1a6ff8e34c9 100644
--- a/app/models/project_services/ci/slack_message.rb
+++ b/app/models/project_services/ci/slack_message.rb
@@ -45,7 +45,7 @@ module Ci
def attachment_message
out = "<#{ci_project_url(project)}|#{project_name}>: "
- out << "Commit <#{ci_namespace_project_commit_url(commit.gl_project.namespace, commit.gl_project, commit.sha)}|\##{commit.id}> "
+ out << "Commit <#{builds_namespace_project_commit_url(commit.gl_project.namespace, commit.gl_project, commit.sha)}|\##{commit.id}> "
out << "(<#{commit_sha_link}|#{commit.short_sha}>) "
out << "of <#{commit_ref_link}|#{commit.ref}> "
out << "by #{commit.git_author_name} " if commit.git_author_name
diff --git a/app/models/project_services/ci/slack_service.rb b/app/models/project_services/ci/slack_service.rb
index ee8e4988826..7064bfe78db 100644
--- a/app/models/project_services/ci/slack_service.rb
+++ b/app/models/project_services/ci/slack_service.rb
@@ -1,6 +1,6 @@
# == Schema Information
#
-# Table name: services
+# Table name: ci_services
#
# id :integer not null, primary key
# type :string(255)
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
index c73c4b058a1..c240213200d 100644
--- a/app/models/project_services/drone_ci_service.rb
+++ b/app/models/project_services/drone_ci_service.rb
@@ -32,7 +32,6 @@ class DroneCiService < CiService
def compose_service_hook
hook = service_hook || build_service_hook
- hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.path}", "&name=#{project.path}", "&access_token=#{token}"].join
hook.enable_ssl_verification = enable_ssl_verification
hook.save
end
diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb
index 4dcd16ede3a..095d04e0df4 100644
--- a/app/models/project_services/gitlab_ci_service.rb
+++ b/app/models/project_services/gitlab_ci_service.rb
@@ -71,7 +71,7 @@ class GitlabCiService < CiService
def build_page(sha, ref)
if project.gitlab_ci_project.present?
- ci_namespace_project_commit_url(project.namespace, project, sha)
+ builds_namespace_project_commit_url(project.namespace, project, sha)
end
end
diff --git a/app/models/project_wiki.rb b/app/models/project_wiki.rb
index 231973fa543..b5fec38378b 100644
--- a/app/models/project_wiki.rb
+++ b/app/models/project_wiki.rb
@@ -86,6 +86,8 @@ class ProjectWiki
commit = commit_details(:created, message, title)
wiki.write_page(title, format, content, commit)
+
+ update_project_activity
rescue Gollum::DuplicatePageError => e
@error_message = "Duplicate page: #{e.message}"
return false
@@ -95,10 +97,14 @@ class ProjectWiki
commit = commit_details(:updated, message, page.title)
wiki.update_page(page, page.name, format, content, commit)
+
+ update_project_activity
end
def delete_page(page, message = nil)
wiki.delete_page(page, commit_details(:deleted, message, page.title))
+
+ update_project_activity
end
def page_title_and_dir(title)
@@ -146,4 +152,8 @@ class ProjectWiki
def path_to_repo
@path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git")
end
+
+ def update_project_activity
+ @project.touch(:last_activity_at)
+ end
end
diff --git a/app/models/release.rb b/app/models/release.rb
new file mode 100644
index 00000000000..89f70278af5
--- /dev/null
+++ b/app/models/release.rb
@@ -0,0 +1,17 @@
+# == Schema Information
+#
+# Table name: releases
+#
+# id :integer not null, primary key
+# tag :string(255)
+# description :text
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+#
+
+class Release < ActiveRecord::Base
+ belongs_to :project
+
+ validates :description, :project, :tag, presence: true
+end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 8b51602bc23..f76b770e867 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -8,6 +8,14 @@ class Repository
attr_accessor :raw_repository, :path_with_namespace, :project
+ def self.clean_old_archives
+ repository_downloads_path = Gitlab.config.gitlab.repository_downloads_path
+
+ return unless File.directory?(repository_downloads_path)
+
+ Gitlab::Popen.popen(%W(find #{repository_downloads_path} -not -path #{repository_downloads_path} -mmin +120 -delete))
+ end
+
def initialize(path_with_namespace, default_branch = nil, project = nil)
@path_with_namespace = path_with_namespace
@project = project
@@ -36,6 +44,19 @@ class Repository
raw_repository.empty?
end
+ #
+ # Git repository can contains some hidden refs like:
+ # /refs/notes/*
+ # /refs/git-as-svn/*
+ # /refs/pulls/*
+ # This refs by default not visible in project page and not cloned to client side.
+ #
+ # This method return true if repository contains some content visible in project page.
+ #
+ def has_visible_content?
+ !raw_repository.branches.empty?
+ end
+
def commit(id = 'HEAD')
return nil unless raw_repository
commit = Gitlab::Git::Commit.find(raw_repository, id)
@@ -46,13 +67,16 @@ class Repository
end
def commits(ref, path = nil, limit = nil, offset = nil, skip_merges = false)
- commits = Gitlab::Git::Commit.where(
+ options = {
repo: raw_repository,
ref: ref,
path: path,
limit: limit,
offset: offset,
- )
+ follow: path.present?
+ }
+
+ commits = Gitlab::Git::Commit.where(options)
commits = Commit.decorate(commits, @project) if commits.present?
commits
end
@@ -63,6 +87,15 @@ class Repository
commits
end
+ def find_commits_by_message(query)
+ # Limited to 1000 commits for now, could be parameterized?
+ args = %W(#{Gitlab.config.git.bin_path} log --pretty=%H --max-count 1000 --grep=#{query})
+
+ git_log_results = Gitlab::Popen.popen(args, path_to_repo).first.lines.map(&:chomp)
+ commits = git_log_results.map { |c| commit(c) }
+ commits
+ end
+
def find_branch(name)
branches.find { |branch| branch.name == name }
end
@@ -263,20 +296,12 @@ class Repository
end
def last_commit_for_path(sha, path)
- args = %W(git rev-list --max-count=1 #{sha} -- #{path})
+ args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path})
sha = Gitlab::Popen.popen(args, path_to_repo).first.strip
commit(sha)
end
# Remove archives older than 2 hours
- def clean_old_archives
- repository_downloads_path = Gitlab.config.gitlab.repository_downloads_path
-
- return unless File.directory?(repository_downloads_path)
-
- Gitlab::Popen.popen(%W(find #{repository_downloads_path} -not -path #{repository_downloads_path} -mmin +120 -delete))
- end
-
def branches_sorted_by(value)
case value
when 'recently_updated'
@@ -312,13 +337,7 @@ class Repository
end
def blob_for_diff(commit, diff)
- file = blob_at(commit.id, diff.new_path)
-
- unless file
- file = prev_blob_for_diff(commit, diff)
- end
-
- file
+ blob_at(commit.id, diff.file_path)
end
def prev_blob_for_diff(commit, diff)
@@ -327,8 +346,8 @@ class Repository
end
end
- def branch_names_contains(sha)
- args = %W(git branch --contains #{sha})
+ def refs_contains_sha(ref_type, sha)
+ args = %W(#{Gitlab.config.git.bin_path} #{ref_type} --contains #{sha})
names = Gitlab::Popen.popen(args, path_to_repo).first
if names.respond_to?(:split)
@@ -344,21 +363,12 @@ class Repository
end
end
- def tag_names_contains(sha)
- args = %W(git tag --contains #{sha})
- names = Gitlab::Popen.popen(args, path_to_repo).first
-
- if names.respond_to?(:split)
- names = names.split("\n").map(&:strip)
-
- names.each do |name|
- name.slice! '* '
- end
+ def branch_names_contains(sha)
+ refs_contains_sha('branch', sha)
+ end
- names
- else
- []
- end
+ def tag_names_contains(sha)
+ refs_contains_sha('tag', sha)
end
def branches
@@ -480,9 +490,13 @@ class Repository
end
end
+ def merge_base(first_commit_id, second_commit_id)
+ rugged.merge_base(first_commit_id, second_commit_id)
+ end
+
def search_files(query, ref)
offset = 2
- args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} #{query} #{ref || root_ref})
+ args = %W(#{Gitlab.config.git.bin_path} grep -i -n --before-context #{offset} --after-context #{offset} -e #{query} #{ref || root_ref})
Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/)
end
@@ -514,7 +528,7 @@ class Repository
end
def fetch_ref(source_path, source_ref, target_ref)
- args = %W(git fetch #{source_path} #{source_ref}:#{target_ref})
+ args = %W(#{Gitlab.config.git.bin_path} fetch -f #{source_path} #{source_ref}:#{target_ref})
Gitlab::Popen.popen(args, path_to_repo)
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 17ccb3b8788..61abea1f6ea 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -54,6 +54,7 @@
# public_email :string(255) default(""), not null
# dashboard :integer default(0)
# project_view :integer default(0)
+# consumed_timestep :integer
# layout :integer default(0)
#
@@ -183,7 +184,7 @@ class User < ActiveRecord::Base
# User's Project preference
# Note: When adding an option, it MUST go on the end of the array.
- enum project_view: [:readme, :activity]
+ enum project_view: [:readme, :activity, :files]
alias_attribute :private_token, :authentication_token
@@ -235,21 +236,16 @@ class User < ActiveRecord::Base
# Find a User by their primary email or any associated secondary email
def find_by_any_email(email)
- user_table = arel_table
- email_table = Email.arel_table
-
- # Use ARel to build a query:
- query = user_table.
- # SELECT "users".* FROM "users"
- project(user_table[Arel.star]).
- # LEFT OUTER JOIN "emails"
- join(email_table, Arel::Nodes::OuterJoin).
- # ON "users"."id" = "emails"."user_id"
- on(user_table[:id].eq(email_table[:user_id])).
- # WHERE ("user"."email" = '<email>' OR "emails"."email" = '<email>')
- where(user_table[:email].eq(email).or(email_table[:email].eq(email)))
-
- find_by_sql(query.to_sql).first
+ sql = 'SELECT *
+ FROM users
+ WHERE id IN (
+ SELECT id FROM users WHERE email = :email
+ UNION
+ SELECT emails.user_id FROM emails WHERE email = :email
+ )
+ LIMIT 1;'
+
+ User.find_by_sql([sql, { email: email }]).first
end
def filter(filter_name)
@@ -401,15 +397,26 @@ class User < ActiveRecord::Base
end
end
+ def authorized_projects_id
+ @authorized_projects_id ||= begin
+ project_ids = personal_projects.pluck(:id)
+ project_ids.push(*groups_projects.pluck(:id))
+ project_ids.push(*projects.pluck(:id).uniq)
+ end
+ end
+
+ def master_or_owner_projects_id
+ @master_or_owner_projects_id ||= begin
+ scope = { access_level: [ Gitlab::Access::MASTER, Gitlab::Access::OWNER ] }
+ project_ids = personal_projects.pluck(:id)
+ project_ids.push(*groups_projects.where(members: scope).pluck(:id))
+ project_ids.push(*projects.where(members: scope).pluck(:id).uniq)
+ end
+ end
# Projects user has access to
def authorized_projects
- @authorized_projects ||= begin
- project_ids = personal_projects.pluck(:id)
- project_ids.push(*groups_projects.pluck(:id))
- project_ids.push(*projects.pluck(:id).uniq)
- Project.where(id: project_ids)
- end
+ @authorized_projects ||= Project.where(id: authorized_projects_id)
end
def owned_projects
@@ -706,12 +713,15 @@ class User < ActiveRecord::Base
end
def toggle_star(project)
- user_star_project = users_star_projects.
- where(project: project, user: self).take
- if user_star_project
- user_star_project.destroy
- else
- UsersStarProject.create!(project: project, user: self)
+ UsersStarProject.transaction do
+ user_star_project = users_star_projects.
+ where(project: project, user: self).lock(true).first
+
+ if user_star_project
+ user_star_project.destroy
+ else
+ UsersStarProject.create!(project: project, user: self)
+ end
end
end
@@ -764,12 +774,11 @@ class User < ActiveRecord::Base
!solo_owned_groups.present?
end
- def ci_authorized_projects
- @ci_authorized_projects ||= Ci::Project.where(gitlab_id: authorized_projects)
- end
-
def ci_authorized_runners
- Ci::Runner.specific.includes(:runner_projects).
- where(ci_runner_projects: { project_id: ci_authorized_projects } )
+ @ci_authorized_runners ||= begin
+ runner_ids = Ci::RunnerProject.joins(:project).
+ where(ci_projects: { gitlab_id: master_or_owner_projects_id }).select(:runner_id)
+ Ci::Runner.specific.where(id: runner_ids)
+ end
end
end
diff --git a/app/services/archive_repository_service.rb b/app/services/archive_repository_service.rb
index 6414b5a0184..2160bf13e6d 100644
--- a/app/services/archive_repository_service.rb
+++ b/app/services/archive_repository_service.rb
@@ -7,7 +7,7 @@ class ArchiveRepositoryService
end
def execute(options = {})
- project.repository.clean_old_archives
+ RepositoryArchiveCacheWorker.perform_async
metadata = project.repository.archive_metadata(ref, storage_path, format)
raise "Repository or ref not found" if metadata.empty?
diff --git a/app/services/ci/create_builds_service.rb b/app/services/ci/create_builds_service.rb
index c420f3268fd..912eb6258a4 100644
--- a/app/services/ci/create_builds_service.rb
+++ b/app/services/ci/create_builds_service.rb
@@ -1,8 +1,20 @@
module Ci
class CreateBuildsService
- def execute(commit, stage, ref, tag, user, trigger_request)
+ def execute(commit, stage, ref, tag, user, trigger_request, status)
builds_attrs = commit.config_processor.builds_for_stage_and_ref(stage, ref, tag)
+ # check when to create next build
+ builds_attrs = builds_attrs.select do |build_attrs|
+ case build_attrs[:when]
+ when 'on_success'
+ status == 'success'
+ when 'on_failure'
+ status == 'failed'
+ when 'always'
+ %w(success failed).include?(status)
+ end
+ end
+
builds_attrs.map do |build_attrs|
# don't create the same build twice
unless commit.builds.find_by(ref: ref, tag: tag, trigger_request: trigger_request, name: build_attrs[:name])
diff --git a/app/services/ci/image_for_build_service.rb b/app/services/ci/image_for_build_service.rb
index b95835ba093..b8d24193035 100644
--- a/app/services/ci/image_for_build_service.rb
+++ b/app/services/ci/image_for_build_service.rb
@@ -1,17 +1,15 @@
module Ci
class ImageForBuildService
def execute(project, params)
- image_name =
- if params[:sha]
- commit = project.commits.find_by(sha: params[:sha])
- image_for_commit(commit)
- elsif params[:ref]
- commit = project.last_commit_for_ref(params[:ref])
- image_for_commit(commit)
- else
- 'build-unknown.svg'
+ sha = params[:sha]
+ sha ||=
+ if params[:ref]
+ project.gl_project.commit(params[:ref]).try(:sha)
end
+ commit = project.commits.ordered.find_by(sha: sha)
+ image_name = image_for_commit(commit)
+
image_path = Rails.root.join('public/ci', image_name)
OpenStruct.new(
diff --git a/app/services/compare_service.rb b/app/services/compare_service.rb
index bfe6a3dc4be..ec581658fc1 100644
--- a/app/services/compare_service.rb
+++ b/app/services/compare_service.rb
@@ -3,7 +3,7 @@ require 'securerandom'
# Compare 2 branches for one repo or between repositories
# and return Gitlab::CompareResult object that responds to commits and diffs
class CompareService
- def execute(source_project, source_branch, target_project, target_branch)
+ def execute(source_project, source_branch, target_project, target_branch, diff_options = {})
source_commit = source_project.commit(source_branch)
return unless source_commit
@@ -25,7 +25,7 @@ class CompareService
target_project.repository.raw_repository,
target_branch,
source_sha,
- )
+ ), diff_options
)
end
end
diff --git a/app/services/create_tag_service.rb b/app/services/create_tag_service.rb
index 1a7318048b3..9917119fce2 100644
--- a/app/services/create_tag_service.rb
+++ b/app/services/create_tag_service.rb
@@ -1,7 +1,7 @@
require_relative 'base_service'
class CreateTagService < BaseService
- def execute(tag_name, ref, message)
+ def execute(tag_name, ref, message, release_description = nil)
valid_tag = Gitlab::GitRefValidator.validate(tag_name)
if valid_tag == false
return error('Tag name invalid')
@@ -19,8 +19,12 @@ class CreateTagService < BaseService
new_tag = repository.find_tag(tag_name)
if new_tag
- push_data = create_push_data(project, current_user, new_tag)
+ if release_description
+ release = project.releases.find_or_initialize_by(tag: tag_name)
+ release.update_attributes(description: release_description)
+ end
+ push_data = create_push_data(project, current_user, new_tag)
EventCreateService.new.push(project, current_user, push_data)
project.execute_hooks(push_data.dup, :tag_push_hooks)
project.execute_services(push_data.dup, :tag_push_hooks)
diff --git a/app/services/delete_tag_service.rb b/app/services/delete_tag_service.rb
index 0c836401136..de3352a6756 100644
--- a/app/services/delete_tag_service.rb
+++ b/app/services/delete_tag_service.rb
@@ -11,8 +11,10 @@ class DeleteTagService < BaseService
end
if repository.rm_tag(tag_name)
+ release = project.releases.find_by(tag: tag_name)
+ release.destroy if release
+
push_data = build_push_data(tag)
-
EventCreateService.new.push(project, current_user, push_data)
project.execute_hooks(push_data.dup, :tag_push_hooks)
project.execute_services(push_data.dup, :tag_push_hooks)
diff --git a/app/services/files/create_dir_service.rb b/app/services/files/create_dir_service.rb
index 71272fb5707..6107254a34e 100644
--- a/app/services/files/create_dir_service.rb
+++ b/app/services/files/create_dir_service.rb
@@ -5,5 +5,16 @@ module Files
def commit
repository.commit_dir(current_user, @file_path, @commit_message, @target_branch)
end
+
+ def validate
+ super
+
+ unless @file_path =~ Gitlab::Regex.file_path_regex
+ raise_error(
+ 'Your changes could not be committed, because the file path ' +
+ Gitlab::Regex.file_path_regex_message
+ )
+ end
+ end
end
end
diff --git a/app/services/files/create_service.rb b/app/services/files/create_service.rb
index c8e3a910bba..2348920cc58 100644
--- a/app/services/files/create_service.rb
+++ b/app/services/files/create_service.rb
@@ -9,12 +9,17 @@ module Files
def validate
super
- file_name = File.basename(@file_path)
+ if @file_path =~ Gitlab::Regex.directory_traversal_regex
+ raise_error(
+ 'Your changes could not be committed, because the file name ' +
+ Gitlab::Regex.directory_traversal_regex_message
+ )
+ end
- unless file_name =~ Gitlab::Regex.file_name_regex
+ unless @file_path =~ Gitlab::Regex.file_path_regex
raise_error(
'Your changes could not be committed, because the file name ' +
- Gitlab::Regex.file_name_regex_message
+ Gitlab::Regex.file_path_regex_message
)
end
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index 81d47602f13..ccb6b97858c 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -49,15 +49,18 @@ class GitPushService
elsif push_to_existing_branch?(ref, oldrev)
# Collect data for this git push
@push_commits = project.repository.commits_between(oldrev, newrev)
- project.update_merge_requests(oldrev, newrev, ref, @user)
process_commit_messages(ref)
end
+ # Update merge requests that may be affected by this push. A new branch
+ # could cause the last commit of a merge request to change.
+ project.update_merge_requests(oldrev, newrev, ref, @user)
+
@push_data = build_push_data(oldrev, newrev, ref)
# If CI was disabled but .gitlab-ci.yml file was pushed
# we enable CI automatically
- if !project.gitlab_ci? && gitlab_ci_yaml?(newrev)
+ if !project.builds_enabled? && gitlab_ci_yaml?(newrev)
project.enable_ci
end
@@ -76,7 +79,7 @@ class GitPushService
authors = Hash.new do |hash, commit|
email = commit.author_email
- return hash[email] if hash.has_key?(email)
+ next hash[email] if hash.has_key?(email)
hash[email] = commit_user(commit)
end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index 2b5426ad452..aa1fd79d22d 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -22,24 +22,27 @@ module Issues
issue, issue.labels - old_labels, old_labels - issue.labels)
end
- if issue.previous_changes.include?('milestone_id')
- create_milestone_note(issue)
- end
+ handle_changes(issue)
+ issue.create_new_cross_references!(current_user)
+ execute_hooks(issue, 'update')
+ end
- if issue.previous_changes.include?('assignee_id')
- create_assignee_note(issue)
- notification_service.reassigned_issue(issue, current_user)
- end
+ issue
+ end
- if issue.previous_changes.include?('title')
- create_title_change_note(issue, issue.previous_changes['title'].first)
- end
+ def handle_changes(issue)
+ if issue.previous_changes.include?('milestone_id')
+ create_milestone_note(issue)
+ end
- issue.create_new_cross_references!
- execute_hooks(issue, 'update')
+ if issue.previous_changes.include?('assignee_id')
+ create_assignee_note(issue)
+ notification_service.reassigned_issue(issue, current_user)
end
- issue
+ if issue.previous_changes.include?('title')
+ create_title_change_note(issue, issue.previous_changes['title'].first)
+ end
end
end
end
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index aceb8cb9021..8f25c5e2496 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -6,6 +6,7 @@ module MergeRequests
#
class PostMergeService < MergeRequests::BaseService
def execute(merge_request)
+ close_issues(merge_request)
merge_request.mark_as_merged
create_merge_event(merge_request, current_user)
create_note(merge_request)
@@ -15,6 +16,15 @@ module MergeRequests
private
+ def close_issues(merge_request)
+ return unless merge_request.target_branch == project.default_branch
+
+ closed_issues = merge_request.closes_issues(current_user)
+ closed_issues.each do |issue|
+ Issues::CloseService.new(project, current_user, {}).execute(issue, merge_request)
+ end
+ end
+
def create_merge_event(merge_request, current_user)
EventCreateService.new.merge_mr(merge_request, current_user)
end
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index e903e48e3cd..e180edb4bf3 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -5,13 +5,20 @@ module MergeRequests
@oldrev, @newrev = oldrev, newrev
@branch_name = Gitlab::Git.ref_name(ref)
- @fork_merge_requests = @project.fork_merge_requests.opened
- @commits = @project.repository.commits_between(oldrev, newrev)
+ find_new_commits
+ # Be sure to close outstanding MRs before reloading them to avoid generating an
+ # empty diff during a manual merge
close_merge_requests
reload_merge_requests
- execute_mr_web_hooks
+
+ # Leave a system note if a branch was deleted/added
+ if branch_added? || branch_removed?
+ comment_mr_branch_presence_changed
+ end
+
comment_mr_with_commits
+ execute_mr_web_hooks
true
end
@@ -31,7 +38,6 @@ module MergeRequests
commit_ids.include?(merge_request.last_commit.id)
end
-
merge_requests.uniq.select(&:source_project).each do |merge_request|
MergeRequests::PostMergeService.
new(merge_request.target_project, @current_user).
@@ -47,7 +53,7 @@ module MergeRequests
# Note: we should update merge requests from forks too
def reload_merge_requests
merge_requests = @project.merge_requests.opened.by_branch(@branch_name).to_a
- merge_requests += @fork_merge_requests.by_branch(@branch_name).to_a
+ merge_requests += fork_merge_requests.by_branch(@branch_name).to_a
merge_requests = filter_merge_requests(merge_requests)
merge_requests.each do |merge_request|
@@ -70,13 +76,48 @@ module MergeRequests
end
end
+ def find_new_commits
+ if branch_added?
+ @commits = []
+
+ merge_request = merge_requests_for_source_branch.first
+ return unless merge_request
+
+ last_commit = merge_request.last_commit
+
+ begin
+ # Since any number of commits could have been made to the restored branch,
+ # find the common root to see what has been added.
+ common_ref = @project.repository.merge_base(last_commit.id, @newrev)
+ # If the a commit no longer exists in this repo, gitlab_git throws
+ # a Rugged::OdbError. This is fixed in https://gitlab.com/gitlab-org/gitlab_git/merge_requests/52
+ @commits = @project.repository.commits_between(common_ref, @newrev) if common_ref
+ rescue
+ end
+ elsif branch_removed?
+ # No commits for a deleted branch.
+ @commits = []
+ else
+ @commits = @project.repository.commits_between(@oldrev, @newrev)
+ end
+ end
+
+ # Add comment about branches being deleted or added to merge requests
+ def comment_mr_branch_presence_changed
+ presence = branch_added? ? :add : :delete
+
+ merge_requests_for_source_branch.each do |merge_request|
+ SystemNoteService.change_branch_presence(
+ merge_request, merge_request.project, @current_user,
+ :source, @branch_name, presence)
+ end
+ end
+
# Add comment about pushing new commits to merge requests
def comment_mr_with_commits
- merge_requests = @project.origin_merge_requests.opened.where(source_branch: @branch_name).to_a
- merge_requests += @fork_merge_requests.where(source_branch: @branch_name).to_a
- merge_requests = filter_merge_requests(merge_requests)
+ return unless @commits.present?
- merge_requests.each do |merge_request|
+ merge_requests_for_source_branch.each do |merge_request|
mr_commit_ids = Set.new(merge_request.commits.map(&:id))
new_commits, existing_commits = @commits.partition do |commit|
@@ -91,14 +132,7 @@ module MergeRequests
# Call merge request webhook with update branches
def execute_mr_web_hooks
- merge_requests = @project.origin_merge_requests.opened
- .where(source_branch: @branch_name)
- .to_a
- merge_requests += @fork_merge_requests.where(source_branch: @branch_name)
- .to_a
- merge_requests = filter_merge_requests(merge_requests)
-
- merge_requests.each do |merge_request|
+ merge_requests_for_source_branch.each do |merge_request|
execute_hooks(merge_request, 'update')
end
end
@@ -106,5 +140,25 @@ module MergeRequests
def filter_merge_requests(merge_requests)
merge_requests.uniq.select(&:source_project)
end
+
+ def merge_requests_for_source_branch
+ @source_merge_requests ||= begin
+ merge_requests = @project.origin_merge_requests.opened.where(source_branch: @branch_name).to_a
+ merge_requests += fork_merge_requests.where(source_branch: @branch_name).to_a
+ filter_merge_requests(merge_requests)
+ end
+ end
+
+ def fork_merge_requests
+ @fork_merge_requests ||= @project.fork_merge_requests.opened
+ end
+
+ def branch_added?
+ Gitlab::Git.blank_ref?(@oldrev)
+ end
+
+ def branch_removed?
+ Gitlab::Git.blank_ref?(@newrev)
+ end
end
end
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index ebbe0af803b..d2849e5193f 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -35,35 +35,38 @@ module MergeRequests
)
end
- if merge_request.previous_changes.include?('target_branch')
- create_branch_change_note(merge_request, 'target',
- merge_request.previous_changes['target_branch'].first,
- merge_request.target_branch)
- end
+ handle_changes(merge_request)
+ merge_request.create_new_cross_references!(current_user)
+ execute_hooks(merge_request, 'update')
+ end
- if merge_request.previous_changes.include?('milestone_id')
- create_milestone_note(merge_request)
- end
+ merge_request
+ end
- if merge_request.previous_changes.include?('assignee_id')
- create_assignee_note(merge_request)
- notification_service.reassigned_merge_request(merge_request, current_user)
- end
+ def handle_changes(merge_request)
+ if merge_request.previous_changes.include?('target_branch')
+ create_branch_change_note(merge_request, 'target',
+ merge_request.previous_changes['target_branch'].first,
+ merge_request.target_branch)
+ end
- if merge_request.previous_changes.include?('title')
- create_title_change_note(merge_request, merge_request.previous_changes['title'].first)
- end
+ if merge_request.previous_changes.include?('milestone_id')
+ create_milestone_note(merge_request)
+ end
- if merge_request.previous_changes.include?('target_branch') ||
- merge_request.previous_changes.include?('source_branch')
- merge_request.mark_as_unchecked
- end
+ if merge_request.previous_changes.include?('assignee_id')
+ create_assignee_note(merge_request)
+ notification_service.reassigned_merge_request(merge_request, current_user)
+ end
- merge_request.create_new_cross_references!
- execute_hooks(merge_request, 'update')
+ if merge_request.previous_changes.include?('title')
+ create_title_change_note(merge_request, merge_request.previous_changes['title'].first)
end
- merge_request
+ if merge_request.previous_changes.include?('target_branch') ||
+ merge_request.previous_changes.include?('source_branch')
+ merge_request.mark_as_unchecked
+ end
end
end
end
diff --git a/app/services/milestones/group_service.rb b/app/services/milestones/group_service.rb
deleted file mode 100644
index 11d702f1e7b..00000000000
--- a/app/services/milestones/group_service.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-module Milestones
- class GroupService < Milestones::BaseService
- def initialize(project_milestones)
- @project_milestones = project_milestones.group_by(&:title)
- end
-
- def execute
- build(@project_milestones)
- end
-
- def milestone(title)
- if title
- group_milestone = @project_milestones[title].group_by(&:title)
- build(group_milestone).first
- else
- nil
- end
- end
-
- private
-
- def build(milestone)
- milestone.map{ |title, milestones| GroupMilestone.new(title, milestones) }
- end
- end
-end
diff --git a/app/services/notes/update_service.rb b/app/services/notes/update_service.rb
index 6c2f08e5963..72e2f78008d 100644
--- a/app/services/notes/update_service.rb
+++ b/app/services/notes/update_service.rb
@@ -4,7 +4,7 @@ module Notes
return note unless note.editable?
note.update_attributes(params.merge(updated_by: current_user))
- note.create_new_cross_references!
+ note.create_new_cross_references!(current_user)
note.reset_events_cache
note
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index faf1ee008e7..5b84527eccf 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -94,8 +94,6 @@ module Projects
@project.team << [current_user, :master, current_user]
end
- @project.update_column(:last_activity_at, @project.created_at)
-
if @project.import?
@project.import_start
end
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index 46374a3909a..5da1c7afd92 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -17,7 +17,7 @@ module Projects
new_project = CreateService.new(current_user, new_params).execute
if new_project.persisted?
- if @project.gitlab_ci?
+ if @project.builds_enabled?
new_project.enable_ci
settings = @project.gitlab_ci_project.attributes.select do |attr_name, value|
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index 9a5fe4af9dd..8b5143e1eb7 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -33,17 +33,7 @@ class SystemHooksService
)
end
when Project
- owner = model.owner
-
- data.merge!({
- name: model.name,
- path: model.path,
- path_with_namespace: model.path_with_namespace,
- project_id: model.id,
- owner_name: owner.name,
- owner_email: owner.respond_to?(:email) ? owner.email : "",
- project_visibility: Project.visibility_levels.key(model.visibility_level_field).downcase
- })
+ data.merge!(project_data(model))
when User
data.merge!({
name: model.name,
@@ -51,16 +41,7 @@ class SystemHooksService
user_id: model.id
})
when ProjectMember
- data.merge!({
- project_name: model.project.name,
- project_path: model.project.path,
- project_path_with_namespace: model.project.path_with_namespace,
- project_id: model.project.id,
- user_name: model.user.name,
- user_email: model.user.email,
- access_level: model.human_access,
- project_visibility: Project.visibility_levels.key(model.project.visibility_level_field).downcase
- })
+ data.merge!(project_member_data(model))
when Group
owner = model.owner
@@ -72,15 +53,7 @@ class SystemHooksService
owner_email: owner.respond_to?(:email) ? owner.email : nil,
)
when GroupMember
- data.merge!(
- group_name: model.group.name,
- group_path: model.group.path,
- group_id: model.group.id,
- user_name: model.user.name,
- user_email: model.user.email,
- user_id: model.user.id,
- group_access: model.human_access,
- )
+ data.merge!(group_member_data(model))
end
end
@@ -96,4 +69,43 @@ class SystemHooksService
"#{model.class.name.downcase}_#{event.to_s}"
end
end
+
+ def project_data(model)
+ owner = model.owner
+
+ {
+ name: model.name,
+ path: model.path,
+ path_with_namespace: model.path_with_namespace,
+ project_id: model.id,
+ owner_name: owner.name,
+ owner_email: owner.respond_to?(:email) ? owner.email : "",
+ project_visibility: Project.visibility_levels.key(model.visibility_level_field).downcase
+ }
+ end
+
+ def project_member_data(model)
+ {
+ project_name: model.project.name,
+ project_path: model.project.path,
+ project_path_with_namespace: model.project.path_with_namespace,
+ project_id: model.project.id,
+ user_name: model.user.name,
+ user_email: model.user.email,
+ access_level: model.human_access,
+ project_visibility: Project.visibility_levels.key(model.project.visibility_level_field).downcase
+ }
+ end
+
+ def group_member_data(model)
+ {
+ group_name: model.group.name,
+ group_path: model.group.path,
+ group_id: model.group.id,
+ user_name: model.user.name,
+ user_email: model.user.email,
+ user_id: model.user.id,
+ group_access: model.human_access,
+ }
+ end
end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 8253c1f780d..708c2f00486 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -168,6 +168,31 @@ class SystemNoteService
create_note(noteable: noteable, project: project, author: author, note: body)
end
+ # Called when a branch in Noteable is added or deleted
+ #
+ # noteable - Noteable object
+ # project - Project owning noteable
+ # author - User performing the change
+ # branch_type - :source or :target
+ # branch - branch name
+ # presence - :add or :delete
+ #
+ # Example Note text:
+ #
+ # "Restored target branch `feature`"
+ #
+ # Returns the created Note object
+ def self.change_branch_presence(noteable, project, author, branch_type, branch, presence)
+ verb =
+ if presence == :add
+ 'restored'
+ else
+ 'deleted'
+ end
+ body = "#{verb} #{branch_type.to_s} branch `#{branch}`".capitalize
+ create_note(noteable: noteable, project: project, author: author, note: body)
+ end
+
# Called when a Mentionable references a Noteable
#
# noteable - Noteable object being referenced
@@ -302,7 +327,7 @@ class SystemNoteService
commit_ids = if count == 1
existing_commits.first.short_id
else
- if oldrev
+ if oldrev && !Gitlab::Git.blank_ref?(oldrev)
"#{Commit.truncate_sha(oldrev)}...#{existing_commits.last.short_id}"
else
"#{existing_commits.first.short_id}..#{existing_commits.last.short_id}"
diff --git a/app/uploaders/artifact_uploader.rb b/app/uploaders/artifact_uploader.rb
new file mode 100644
index 00000000000..b4e0fc5772d
--- /dev/null
+++ b/app/uploaders/artifact_uploader.rb
@@ -0,0 +1,50 @@
+# encoding: utf-8
+class ArtifactUploader < CarrierWave::Uploader::Base
+ storage :file
+
+ attr_accessor :build, :field
+
+ def self.artifacts_path
+ File.expand_path('shared/artifacts/', Rails.root)
+ end
+
+ def self.artifacts_upload_path
+ File.expand_path('shared/artifacts/tmp/uploads/', Rails.root)
+ end
+
+ def self.artifacts_cache_path
+ File.expand_path('shared/artifacts/tmp/cache/', Rails.root)
+ end
+
+ def initialize(build, field)
+ @build, @field = build, field
+ end
+
+ def artifacts_path
+ File.join(build.created_at.utc.strftime('%Y_%m'), build.project.id.to_s, build.id.to_s)
+ end
+
+ def store_dir
+ File.join(ArtifactUploader.artifacts_path, artifacts_path)
+ end
+
+ def cache_dir
+ File.join(ArtifactUploader.artifacts_cache_path, artifacts_path)
+ end
+
+ def file_storage?
+ self.class.storage == CarrierWave::Storage::File
+ end
+
+ def exists?
+ file.try(:exists?)
+ end
+
+ def move_to_cache
+ true
+ end
+
+ def move_to_store
+ true
+ end
+end
diff --git a/app/uploaders/attachment_uploader.rb b/app/uploaders/attachment_uploader.rb
index a9691bee46e..a65a896e41e 100644
--- a/app/uploaders/attachment_uploader.rb
+++ b/app/uploaders/attachment_uploader.rb
@@ -1,26 +1,11 @@
# encoding: utf-8
class AttachmentUploader < CarrierWave::Uploader::Base
+ include UploaderHelper
+
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
-
- def image?
- img_ext = %w(png jpg jpeg gif bmp tiff)
- if file.respond_to?(:extension)
- img_ext.include?(file.extension.downcase)
- else
- # Not all CarrierWave storages respond to :extension
- ext = file.path.split('.').last.downcase
- img_ext.include?(ext)
- end
- rescue
- false
- end
-
- def file_storage?
- self.class.storage == CarrierWave::Storage::File
- end
end
diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb
index 7cad044555b..6135c3ad96f 100644
--- a/app/uploaders/avatar_uploader.rb
+++ b/app/uploaders/avatar_uploader.rb
@@ -1,6 +1,8 @@
# encoding: utf-8
class AvatarUploader < CarrierWave::Uploader::Base
+ include UploaderHelper
+
storage :file
after :store, :reset_events_cache
@@ -9,23 +11,6 @@ class AvatarUploader < CarrierWave::Uploader::Base
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
- def image?
- img_ext = %w(png jpg jpeg gif bmp tiff)
- if file.respond_to?(:extension)
- img_ext.include?(file.extension.downcase)
- else
- # Not all CarrierWave storages respond to :extension
- ext = file.path.split('.').last.downcase
- img_ext.include?(ext)
- end
- rescue
- false
- end
-
- def file_storage?
- self.class.storage == CarrierWave::Storage::File
- end
-
def reset_events_cache(file)
model.reset_events_cache if model.is_a?(User)
end
diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb
index e8211585834..ac920119a85 100644
--- a/app/uploaders/file_uploader.rb
+++ b/app/uploaders/file_uploader.rb
@@ -1,5 +1,7 @@
# encoding: utf-8
class FileUploader < CarrierWave::Uploader::Base
+ include UploaderHelper
+
storage :file
attr_accessor :project, :secret
@@ -28,21 +30,4 @@ class FileUploader < CarrierWave::Uploader::Base
def secure_url
File.join("/uploads", @secret, file.filename)
end
-
- def file_storage?
- self.class.storage == CarrierWave::Storage::File
- end
-
- def image?
- img_ext = %w(png jpg jpeg gif bmp tiff)
- if file.respond_to?(:extension)
- img_ext.include?(file.extension.downcase)
- else
- # Not all CarrierWave storages respond to :extension
- ext = file.path.split('.').last.downcase
- img_ext.include?(ext)
- end
- rescue
- false
- end
end
diff --git a/app/uploaders/lfs_object_uploader.rb b/app/uploaders/lfs_object_uploader.rb
new file mode 100644
index 00000000000..28085b31083
--- /dev/null
+++ b/app/uploaders/lfs_object_uploader.rb
@@ -0,0 +1,29 @@
+# encoding: utf-8
+
+class LfsObjectUploader < CarrierWave::Uploader::Base
+ storage :file
+
+ def store_dir
+ "#{Gitlab.config.lfs.storage_path}/#{model.oid[0,2]}/#{model.oid[2,2]}"
+ end
+
+ def cache_dir
+ "#{Gitlab.config.lfs.storage_path}/tmp/cache"
+ end
+
+ def move_to_cache
+ true
+ end
+
+ def move_to_store
+ true
+ end
+
+ def exists?
+ file.try(:exists?)
+ end
+
+ def filename
+ model.oid[4..-1]
+ end
+end
diff --git a/app/uploaders/uploader_helper.rb b/app/uploaders/uploader_helper.rb
new file mode 100644
index 00000000000..5ef440f3367
--- /dev/null
+++ b/app/uploaders/uploader_helper.rb
@@ -0,0 +1,19 @@
+# Extra methods for uploader
+module UploaderHelper
+ def image?
+ img_ext = %w(png jpg jpeg gif bmp tiff)
+ if file.respond_to?(:extension)
+ img_ext.include?(file.extension.downcase)
+ else
+ # Not all CarrierWave storages respond to :extension
+ ext = file.path.split('.').last.downcase
+ img_ext.include?(ext)
+ end
+ rescue
+ false
+ end
+
+ def file_storage?
+ self.class.storage == CarrierWave::Storage::File
+ end
+end
diff --git a/app/views/abuse_report_mailer/notify.html.haml b/app/views/abuse_report_mailer/notify.html.haml
new file mode 100644
index 00000000000..619533e09a7
--- /dev/null
+++ b/app/views/abuse_report_mailer/notify.html.haml
@@ -0,0 +1,11 @@
+%p
+ #{link_to @abuse_report.user.name, user_url(@abuse_report.user)}
+ (@#{@abuse_report.user.username}) was reported for abuse by
+ #{link_to @abuse_report.reporter.name, user_url(@abuse_report.reporter)}
+ (@#{@abuse_report.reporter.username}).
+
+%blockquote
+ = @abuse_report.message
+
+%p
+ = link_to "View details", abuse_reports_url
diff --git a/app/views/abuse_report_mailer/notify.text.haml b/app/views/abuse_report_mailer/notify.text.haml
new file mode 100644
index 00000000000..7dacf857035
--- /dev/null
+++ b/app/views/abuse_report_mailer/notify.text.haml
@@ -0,0 +1,5 @@
+#{@abuse_report.user.name} (@#{@abuse_report.user.username}) was reported for abuse by #{@abuse_report.reporter.name} (@#{@abuse_report.reporter.username}).
+\
+> #{@abuse_report.message}
+\
+View details: #{admin_abuse_reports_url}
diff --git a/app/views/admin/abuse_reports/index.html.haml b/app/views/admin/abuse_reports/index.html.haml
index 2e8746146d1..40a5fe4628b 100644
--- a/app/views/admin/abuse_reports/index.html.haml
+++ b/app/views/admin/abuse_reports/index.html.haml
@@ -2,16 +2,17 @@
%h3.page-title Abuse Reports
%hr
- if @abuse_reports.present?
- %table.table
- %thead
- %tr
- %th Reported by
- %th Reported at
- %th Message
- %th User
- %th Primary action
- %th
- = render @abuse_reports
+ .table-holder
+ %table.table
+ %thead
+ %tr
+ %th Reported by
+ %th Reported at
+ %th Message
+ %th User
+ %th Primary action
+ %th
+ = render @abuse_reports
= paginate @abuse_reports
- else
%h4 There are no abuse reports
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index a36ae0b766c..ddaf0e0e8ff 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -47,6 +47,12 @@
= f.label :version_check_enabled do
= f.check_box :version_check_enabled
Version check enabled
+ .form-group
+ = f.label :admin_notification_email, class: 'control-label col-sm-2'
+ .col-sm-10
+ = f.text_field :admin_notification_email, class: 'form-control'
+ .help-block
+ Abuse reports will be sent to this address if it is set. Abuse reports are always available in the admin area.
%fieldset
%legend Account and Limit Settings
@@ -124,5 +130,19 @@
= f.text_area :help_page_text, class: 'form-control', rows: 4
.help-block Markdown enabled
+ %fieldset
+ %legend Continuous Integration
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :shared_runners_enabled do
+ = f.check_box :shared_runners_enabled
+ Enable shared runners for a new projects
+
+ .form-group
+ = f.label :max_artifacts_size, 'Maximum artifacts size (MB)', class: 'control-label col-sm-2'
+ .col-sm-10
+ = f.number_field :max_artifacts_size, class: 'form-control'
+
.form-actions
= f.submit 'Save', class: 'btn btn-primary'
diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml
index 0ea2ffeda99..3eb9d61972b 100644
--- a/app/views/admin/applications/show.html.haml
+++ b/app/views/admin/applications/show.html.haml
@@ -3,25 +3,26 @@
Application: #{@application.name}
-%table.table
- %tr
- %td
- Application Id
- %td
- %code#application_id= @application.uid
- %tr
- %td
- Secret:
- %td
- %code#secret= @application.secret
+.table-holder
+ %table.table
+ %tr
+ %td
+ Application Id
+ %td
+ %code#application_id= @application.uid
+ %tr
+ %td
+ Secret:
+ %td
+ %code#secret= @application.secret
- %tr
- %td
- Callback url
- %td
- - @application.redirect_uri.split.each do |uri|
- %div
- %span.monospace= uri
+ %tr
+ %td
+ Callback url
+ %td
+ - @application.redirect_uri.split.each do |uri|
+ %div
+ %span.monospace= uri
.form-actions
= link_to 'Edit', edit_admin_application_path(@application), class: 'btn btn-primary wide pull-left'
= render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10'
diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml
index 3a01e115109..de5bc050cf0 100644
--- a/app/views/admin/background_jobs/show.html.haml
+++ b/app/views/admin/background_jobs/show.html.haml
@@ -12,24 +12,25 @@
%i.fa.fa-exclamation-triangle
There are no running sidekiq processes. Please restart GitLab
- else
- %table.table
- %thead
- %th USER
- %th PID
- %th CPU
- %th MEM
- %th STATE
- %th START
- %th COMMAND
- %tbody
- - @sidekiq_processes.each do |process|
- - next unless process.match(/(sidekiq \d+\.\d+\.\d+.+$)/)
- - data = process.strip.split(' ')
- %tr
- %td= gitlab_config.user
- - 5.times do
- %td= data.shift
- %td= data.join(' ')
+ .table-holder
+ %table.table
+ %thead
+ %th USER
+ %th PID
+ %th CPU
+ %th MEM
+ %th STATE
+ %th START
+ %th COMMAND
+ %tbody
+ - @sidekiq_processes.each do |process|
+ - next unless process.match(/(sidekiq \d+\.\d+\.\d+.+$)/)
+ - data = process.strip.split(' ')
+ %tr
+ %td= gitlab_config.user
+ - 5.times do
+ %td= data.shift
+ %td= data.join(' ')
.clearfix
%p
diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml
index 2bf1689cbc6..841e6971fb2 100644
--- a/app/views/admin/deploy_keys/index.html.haml
+++ b/app/views/admin/deploy_keys/index.html.haml
@@ -5,22 +5,23 @@
.panel-head-actions
= link_to 'New Deploy Key', new_admin_deploy_key_path, class: "btn btn-new btn-sm"
- if @deploy_keys.any?
- %table.table
- %thead.panel-heading
- %tr
- %th Title
- %th Fingerprint
- %th Added at
- %th
- %tbody
- - @deploy_keys.each do |deploy_key|
+ .table-holder
+ %table.table
+ %thead.panel-heading
%tr
- %td
- %strong= deploy_key.title
- %td
- %code.key-fingerprint= deploy_key.fingerprint
- %td
- %span.cgray
- added #{time_ago_with_tooltip(deploy_key.created_at)}
- %td
- = link_to 'Remove', admin_deploy_key_path(deploy_key), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-sm btn-remove delete-key pull-right"
+ %th Title
+ %th Fingerprint
+ %th Added at
+ %th
+ %tbody
+ - @deploy_keys.each do |deploy_key|
+ %tr
+ %td
+ %strong= deploy_key.title
+ %td
+ %code.key-fingerprint= deploy_key.fingerprint
+ %td
+ %span.cgray
+ added #{time_ago_with_tooltip(deploy_key.created_at)}
+ %td
+ = link_to 'Remove', admin_deploy_key_path(deploy_key), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-sm btn-remove delete-key pull-right"
diff --git a/app/views/admin/identities/index.html.haml b/app/views/admin/identities/index.html.haml
index ae57e3adc4d..8358a14445b 100644
--- a/app/views/admin/identities/index.html.haml
+++ b/app/views/admin/identities/index.html.haml
@@ -2,12 +2,13 @@
= render 'admin/users/head'
- if @identities.present?
- %table.table
- %thead
- %tr
- %th Provider
- %th Identifier
- %th
- = render @identities
+ .table-holder
+ %table.table
+ %thead
+ %tr
+ %th Provider
+ %th Identifier
+ %th
+ = render @identities
- else
%h4 This user has no identities
diff --git a/app/views/admin/labels/_form.html.haml b/app/views/admin/labels/_form.html.haml
index ad58a3837f6..a5ace4e7a3b 100644
--- a/app/views/admin/labels/_form.html.haml
+++ b/app/views/admin/labels/_form.html.haml
@@ -31,5 +31,5 @@
= f.submit 'Save', class: 'btn btn-save js-save-button'
= link_to "Cancel", admin_labels_path, class: 'btn btn-cancel'
-:coffeescript
- new Labels
+:javascript
+ new Labels();
diff --git a/app/views/admin/services/index.html.haml b/app/views/admin/services/index.html.haml
index e2377291142..6a5986f496a 100644
--- a/app/views/admin/services/index.html.haml
+++ b/app/views/admin/services/index.html.haml
@@ -2,22 +2,23 @@
%h3.page-title Service templates
%p.light Service template allows you to set default values for project services
-%table.table
- %thead
- %tr
- %th
- %th Service
- %th Description
- %th Last edit
- - @services.sort_by(&:title).each do |service|
- %tr
- %td
- = icon("copy", class: 'clgray')
- %td
- = link_to edit_admin_application_settings_service_path(service.id) do
- %strong= service.title
- %td
- = service.description
- %td.light
- = time_ago_in_words service.updated_at
- ago
+.table-holder
+ %table.table
+ %thead
+ %tr
+ %th
+ %th Service
+ %th Description
+ %th Last edit
+ - @services.sort_by(&:title).each do |service|
+ %tr
+ %td
+ = icon("copy", class: 'clgray')
+ %td
+ = link_to edit_admin_application_settings_service_path(service.id) do
+ %strong= service.title
+ %td
+ = service.description
+ %td.light
+ = time_ago_in_words service.updated_at
+ ago
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
index 4245d0f1eda..8d1cab4137c 100644
--- a/app/views/admin/users/_head.html.haml
+++ b/app/views/admin/users/_head.html.haml
@@ -7,7 +7,7 @@
.pull-right
- unless @user == current_user
- = link_to 'Log in as this user', login_as_admin_user_path(@user), method: :post, class: "btn btn-grouped btn-info"
+ = link_to 'Impersonate', impersonate_admin_user_path(@user), method: :post, class: "btn btn-grouped btn-info"
= link_to edit_admin_user_path(@user), class: "btn btn-grouped" do
%i.fa.fa-pencil-square-o
Edit
diff --git a/app/views/users/_profile.html.haml b/app/views/admin/users/_profile.html.haml
index 90d9980c85c..7d11edc79e2 100644
--- a/app/views/users/_profile.html.haml
+++ b/app/views/admin/users/_profile.html.haml
@@ -16,11 +16,11 @@
- unless user.linkedin.blank?
%li
%span.light LinkedIn:
- %strong= link_to user.linkedin, "http://www.linkedin.com/in/#{user.linkedin}"
+ %strong= link_to user.linkedin, "https://www.linkedin.com/in/#{user.linkedin}"
- unless user.twitter.blank?
%li
%span.light Twitter:
- %strong= link_to user.twitter, "http://www.twitter.com/#{user.twitter}"
+ %strong= link_to user.twitter, "https://twitter.com/#{user.twitter}"
- unless user.website_url.blank?
%li
%span.light Website:
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 231bcb0426f..0848504b7a6 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -14,7 +14,7 @@
%strong
= link_to user_path(@user) do
= @user.username
- = render 'users/profile', user: @user
+ = render 'admin/users/profile', user: @user
.panel.panel-default
.panel-heading
diff --git a/app/views/ci/admin/events/index.html.haml b/app/views/ci/admin/events/index.html.haml
index f9ab0994304..5a5b4dc7c35 100644
--- a/app/views/ci/admin/events/index.html.haml
+++ b/app/views/ci/admin/events/index.html.haml
@@ -1,17 +1,18 @@
-%table.table
- %thead
- %tr
- %th User ID
- %th Description
- %th When
- - @events.each do |event|
- %tr
- %td
- = event.user_id
- %td
- = event.description
- %td.light
- = time_ago_in_words event.updated_at
- ago
+.table-holder
+ %table.table
+ %thead
+ %tr
+ %th User ID
+ %th Description
+ %th When
+ - @events.each do |event|
+ %tr
+ %td
+ = event.user_id
+ %td
+ = event.description
+ %td.light
+ = time_ago_in_words event.updated_at
+ ago
-= paginate @events \ No newline at end of file
+= paginate @events
diff --git a/app/views/ci/admin/projects/index.html.haml b/app/views/ci/admin/projects/index.html.haml
index dc7b041473b..0da8547924b 100644
--- a/app/views/ci/admin/projects/index.html.haml
+++ b/app/views/ci/admin/projects/index.html.haml
@@ -1,15 +1,16 @@
-%table.table
- %thead
- %tr
- %th ID
- %th Name
- %th Last build
- %th Access
- %th Builds
- %th
+.table-holder
+ %table.table
+ %thead
+ %tr
+ %th ID
+ %th Name
+ %th Last build
+ %th Access
+ %th Builds
+ %th
- - @projects.each do |project|
- = render "ci/admin/projects/project", project: project
+ - @projects.each do |project|
+ = render "ci/admin/projects/project", project: project
= paginate @projects
diff --git a/app/views/ci/admin/runner_projects/index.html.haml b/app/views/ci/admin/runner_projects/index.html.haml
index f049b4f4c4e..6b4e3b2cb38 100644
--- a/app/views/ci/admin/runner_projects/index.html.haml
+++ b/app/views/ci/admin/runner_projects/index.html.haml
@@ -1,5 +1,5 @@
%p.lead
- To register new runner visit #{link_to 'this page ', ci_runners_path}
+ To register a new runner visit #{link_to 'this page ', ci_runners_path}
.row
.col-md-8
diff --git a/app/views/ci/admin/runners/index.html.haml b/app/views/ci/admin/runners/index.html.haml
index 01ce81b4476..bacaccfbffa 100644
--- a/app/views/ci/admin/runners/index.html.haml
+++ b/app/views/ci/admin/runners/index.html.haml
@@ -1,5 +1,5 @@
%p.lead
- %span To register new runner you should enter the following registration token. With this token the runner will request a unique runner token and use that for future communication.
+ %span To register a new runner you should enter the following registration token. With this token the runner will request a unique runner token and use that for future communication.
%code #{GitlabCi::REGISTRATION_TOKEN}
.bs-callout
@@ -21,7 +21,7 @@
\- run builds from assigned projects
%li
%span.label.label-danger paused
- \- runner will not receive any new build
+ \- runner will not receive any new builds
.append-bottom-20.clearfix
.pull-left
@@ -35,18 +35,19 @@
%br
-%table.table
- %thead
- %tr
- %th Type
- %th Runner token
- %th Description
- %th Projects
- %th Builds
- %th Tags
- %th Last contact
- %th
+.table-holder
+ %table.table
+ %thead
+ %tr
+ %th Type
+ %th Runner token
+ %th Description
+ %th Projects
+ %th Builds
+ %th Tags
+ %th Last contact
+ %th
- - @runners.each do |runner|
- = render "ci/admin/runners/runner", runner: runner
+ - @runners.each do |runner|
+ = render "ci/admin/runners/runner", runner: runner
= paginate @runners
diff --git a/app/views/ci/admin/runners/show.html.haml b/app/views/ci/admin/runners/show.html.haml
index 92787b2e6ac..1498db46a80 100644
--- a/app/views/ci/admin/runners/show.html.haml
+++ b/app/views/ci/admin/runners/show.html.haml
@@ -13,13 +13,13 @@
- if @runner.shared?
.bs-callout.bs-callout-success
- %h4 This runner will process build from ALL UNASSIGNED projects
+ %h4 This runner will process builds from ALL UNASSIGNED projects
%p
If you want runners to build only specific projects, enable them in the table below.
Keep in mind that this is a one way transition.
- else
.bs-callout.bs-callout-info
- %h4 This runner will process build only from ASSIGNED projects
+ %h4 This runner will process builds only from ASSIGNED projects
%p You can't make this a shared runner.
%hr
= form_for @runner, url: ci_admin_runner_path(@runner), html: { class: 'form-horizontal' } do |f|
@@ -53,13 +53,14 @@
%th
- @runner.runner_projects.each do |runner_project|
- project = runner_project.project
- %tr.alert-info
- %td
- %strong
- = project.name
- %td
- .pull-right
- = link_to 'Disable', [:ci, :admin, project, runner_project], method: :delete, class: 'btn btn-danger btn-xs'
+ - if project.gl_project
+ %tr.alert-info
+ %td
+ %strong
+ = project.name
+ %td
+ .pull-right
+ = link_to 'Disable', [:ci, :admin, project, runner_project], method: :delete, class: 'btn btn-danger btn-xs'
%table.table
%thead
@@ -103,21 +104,26 @@
%th Finished at
- @builds.each do |build|
+ - gl_project = build.gl_project
%tr.build
%td.id
- - gl_project = build.project.gl_project
- = link_to namespace_project_build_path(gl_project.namespace, gl_project, build) do
+ - if gl_project
+ = link_to namespace_project_build_path(gl_project.namespace, gl_project, build) do
+ = build.id
+ - else
= build.id
%td.status
= ci_status_with_icon(build.status)
%td.status
- = build.project.name
+ - if gl_project
+ = gl_project.name_with_namespace
%td.build-link
- = link_to ci_status_path(build.commit) do
- %strong #{build.commit.short_sha}
+ - if gl_project
+ = link_to ci_status_path(build.commit) do
+ %strong #{build.commit.short_sha}
%td.timestamp
- if build.finished_at
diff --git a/app/views/ci/events/index.html.haml b/app/views/ci/events/index.html.haml
deleted file mode 100644
index 779f49b3d3a..00000000000
--- a/app/views/ci/events/index.html.haml
+++ /dev/null
@@ -1,19 +0,0 @@
-%h3.page-title Events
-
-%table.table
- %thead
- %tr
- %th User ID
- %th Description
- %th When
- - @events.each do |event|
- %tr
- %td
- = event.user_id
- %td
- = event.description
- %td.light
- = time_ago_in_words event.updated_at
- ago
-
-= paginate @events \ No newline at end of file
diff --git a/app/views/ci/lints/_create.html.haml b/app/views/ci/lints/_create.html.haml
index e2179e60f3e..77f78caa8d8 100644
--- a/app/views/ci/lints/_create.html.haml
+++ b/app/views/ci/lints/_create.html.haml
@@ -4,29 +4,35 @@
syntax is correct
%i.fa.fa-ok.correct-syntax
- %table.table.table-bordered
- %thead
- %tr
- %th Parameter
- %th Value
- %tbody
- - @stages.each do |stage|
- - @builds.select { |build| build[:stage] == stage }.each do |build|
- %tr
- %td #{stage.capitalize} Job - #{build[:name]}
- %td
- %pre
- = simple_format build[:script]
+ .table-holder
+ %table.table.table-bordered
+ %thead
+ %tr
+ %th Parameter
+ %th Value
+ %tbody
+ - @stages.each do |stage|
+ - @builds.select { |build| build[:stage] == stage }.each do |build|
+ %tr
+ %td #{stage.capitalize} Job - #{build[:name]}
+ %td
+ %pre
+ = simple_format build[:commands]
- %br
- %b Tag list:
- = build[:tags]
- %br
- %b Refs only:
- = build[:only] && build[:only].join(", ")
- %br
- %b Refs except:
- = build[:except] && build[:except].join(", ")
+ %br
+ %b Tag list:
+ = build[:tags]
+ %br
+ %b Refs only:
+ = build[:only] && build[:only].join(", ")
+ %br
+ %b Refs except:
+ = build[:except] && build[:except].join(", ")
+ %br
+ %b When:
+ = build[:when]
+ - if build[:allow_failure]
+ %b Allowed to fail
-else
%p
diff --git a/app/views/ci/lints/show.html.haml b/app/views/ci/lints/show.html.haml
index a9b954771c5..fb9057e4882 100644
--- a/app/views/ci/lints/show.html.haml
+++ b/app/views/ci/lints/show.html.haml
@@ -11,15 +11,17 @@
.controls.pull-left.prepend-top-10
= submit_tag "Validate", class: 'btn btn-success submit-yml'
-
+
%p.text-center.loading
%i.fa.fa-refresh.fa-spin
.results.prepend-top-20
-:coffeescript
- $(".loading").hide()
- $('form').bind 'ajax:beforeSend', ->
- $(".loading").show()
- $('form').bind 'ajax:complete', ->
- $(".loading").hide()
+:javascript
+ $(".loading").hide();
+ $('form').bind('ajax:beforeSend', function() {
+ $(".loading").show();
+ });
+ $('form').bind('ajax:complete', function() {
+ $(".loading").hide();
+ });
diff --git a/app/views/ci/notify/build_fail_email.html.haml b/app/views/ci/notify/build_fail_email.html.haml
index 69689a75022..b0aaea89075 100644
--- a/app/views/ci/notify/build_fail_email.html.haml
+++ b/app/views/ci/notify/build_fail_email.html.haml
@@ -7,13 +7,17 @@
= @project.name
%p
- Commit link: #{gitlab_commit_link(@project, @build.commit.short_sha)}
+ Commit: #{link_to @build.short_sha, namespace_project_commit_path(@build.gl_project.namespace, @build.gl_project, @build.sha)}
%p
Author: #{@build.commit.git_author_name}
%p
Branch: #{@build.ref}
%p
+ Stage: #{@build.stage}
+%p
+ Job: #{@build.name}
+%p
Message: #{@build.commit.git_commit_message}
%p
- Url: #{link_to @build.short_sha, namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build)}
+ Build details: #{link_to "Build #{@build.id}", namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build)}
diff --git a/app/views/ci/notify/build_fail_email.text.erb b/app/views/ci/notify/build_fail_email.text.erb
index 6de5dc10f17..17a3b9b1d33 100644
--- a/app/views/ci/notify/build_fail_email.text.erb
+++ b/app/views/ci/notify/build_fail_email.text.erb
@@ -4,6 +4,8 @@ Status: <%= @build.status %>
Commit: <%= @build.commit.short_sha %>
Author: <%= @build.commit.git_author_name %>
Branch: <%= @build.ref %>
+Stage: <%= @build.stage %>
+Job: <%= @build.name %>
Message: <%= @build.commit.git_commit_message %>
Url: <%= namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build) %>
diff --git a/app/views/ci/notify/build_success_email.html.haml b/app/views/ci/notify/build_success_email.html.haml
index 4e3015a356b..24c439e50eb 100644
--- a/app/views/ci/notify/build_success_email.html.haml
+++ b/app/views/ci/notify/build_success_email.html.haml
@@ -8,13 +8,17 @@
= @project.name
%p
- Commit link: #{gitlab_commit_link(@project, @build.commit.short_sha)}
+ Commit: #{link_to @build.short_sha, namespace_project_commit_path(@build.gl_project.namespace, @build.gl_project, @build.sha)}
%p
Author: #{@build.commit.git_author_name}
%p
Branch: #{@build.ref}
%p
+ Stage: #{@build.stage}
+%p
+ Job: #{@build.name}
+%p
Message: #{@build.commit.git_commit_message}
%p
- Url: #{link_to @build.short_sha, namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build)}
+ Build details: #{link_to "Build #{@build.id}", namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build)}
diff --git a/app/views/ci/notify/build_success_email.text.erb b/app/views/ci/notify/build_success_email.text.erb
index d0a43ae1c12..bc8b978c3d7 100644
--- a/app/views/ci/notify/build_success_email.text.erb
+++ b/app/views/ci/notify/build_success_email.text.erb
@@ -4,6 +4,8 @@ Status: <%= @build.status %>
Commit: <%= @build.commit.short_sha %>
Author: <%= @build.commit.git_author_name %>
Branch: <%= @build.ref %>
+Stage: <%= @build.stage %>
+Job: <%= @build.name %>
Message: <%= @build.commit.git_commit_message %>
Url: <%= namespace_project_build_url(@build.gl_project.namespace, @build.gl_project, @build) %>
diff --git a/app/views/ci/projects/index.html.haml b/app/views/ci/projects/index.html.haml
new file mode 100644
index 00000000000..9c2290bc4a5
--- /dev/null
+++ b/app/views/ci/projects/index.html.haml
@@ -0,0 +1,20 @@
+.wiki
+ %h1
+ GitLab CI is now integrated in GitLab UI
+ %h2 For existing projects
+
+ %p
+ Check the following pages to find the CI status you're looking for:
+
+ %ul
+ %li Projects page - shows CI status for each project.
+ %li Project commits page - show CI status for each commit.
+
+
+
+ %h2 For new projects
+
+ %p
+ If you want to enable CI for a new project it is easy as adding
+ = link_to ".gitlab-ci.yml", "http://doc.gitlab.com/ce/ci/yaml/README.html"
+ file to your repository
diff --git a/app/views/ci/user_sessions/new.html.haml b/app/views/ci/user_sessions/new.html.haml
index 308b217ea78..b8d9a1d7089 100644
--- a/app/views/ci/user_sessions/new.html.haml
+++ b/app/views/ci/user_sessions/new.html.haml
@@ -1,8 +1,7 @@
.login-block
%h2 Login using GitLab account
%p.light
- Make sure you have account on GitLab server
+ Make sure you have an account on the GitLab server
= link_to GitlabCi.config.gitlab_server.url, GitlabCi.config.gitlab_server.url, no_turbolink
%hr
= link_to "Login with GitLab", auth_ci_user_sessions_path(state: params[:state]), no_turbolink.merge( class: 'btn btn-login btn-success' )
-
diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml
index c249f5cacec..f3f3f58111e 100644
--- a/app/views/dashboard/groups/index.html.haml
+++ b/app/views/dashboard/groups/index.html.haml
@@ -16,4 +16,4 @@
- group = group_member.group
= render 'shared/groups/group', group: group, group_member: group_member
-= paginate @group_members
+= paginate @group_members, theme: 'gitlab'
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index 21b25c3986e..635251e2374 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -10,10 +10,10 @@
.milestones
%ul.content-list
- - if @dashboard_milestones.blank?
+ - if @milestones.blank?
%li
.nothing-here-block No milestones to show
- else
- - @dashboard_milestones.each do |milestone|
+ - @milestones.each do |milestone|
= render 'milestone', milestone: milestone
- = paginate @dashboard_milestones, theme: "gitlab"
+ = paginate @milestones, theme: "gitlab"
diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml
index d5c4a44fef6..83077a398bd 100644
--- a/app/views/dashboard/milestones/show.html.haml
+++ b/app/views/dashboard/milestones/show.html.haml
@@ -1,82 +1,84 @@
-- page_title @dashboard_milestone.title, "Milestones"
+- page_title @milestone.title, "Milestones"
%h4.page-title
- .issue-box{ class: "issue-box-#{@dashboard_milestone.closed? ? 'closed' : 'open'}" }
- - if @dashboard_milestone.closed?
+ .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" }
+ - if @milestone.closed?
Closed
- else
Open
- Milestone #{@dashboard_milestone.title}
+ Milestone #{@milestone.title}
%hr
-- if (@dashboard_milestone.total_items_count == @dashboard_milestone.closed_items_count) && @dashboard_milestone.active?
+- if @milestone.complete? && @milestone.active?
.alert.alert-success
%span All issues for this milestone are closed. You may close the milestone now.
.description
-%table.table
- %thead
- %tr
- %th Project
- %th Open issues
- %th State
- %th Due date
- - @dashboard_milestone.milestones.each do |milestone|
- %tr
- %td
- = link_to "#{milestone.project.name_with_namespace}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
- %td
- = milestone.issues.opened.count
- %td
- - if milestone.closed?
- Closed
- - else
- Open
- %td
- = milestone.expires_at
+
+.table-holder
+ %table.table
+ %thead
+ %tr
+ %th Project
+ %th Open issues
+ %th State
+ %th Due date
+ - @milestone.milestones.each do |milestone|
+ %tr
+ %td
+ = link_to "#{milestone.project.name_with_namespace}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
+ %td
+ = milestone.issues.opened.count
+ %td
+ - if milestone.closed?
+ Closed
+ - else
+ Open
+ %td
+ = milestone.expires_at
.context
%p.lead
Progress:
- #{@dashboard_milestone.closed_items_count} closed
+ #{@milestone.closed_items_count} closed
&ndash;
- #{@dashboard_milestone.open_items_count} open
- = milestone_progress_bar(@dashboard_milestone)
+ #{@milestone.open_items_count} open
+ = milestone_progress_bar(@milestone)
%ul.nav.nav-tabs
%li.active
= link_to '#tab-issues', 'data-toggle' => 'tab' do
Issues
- %span.badge= @dashboard_milestone.issue_count
+ %span.badge= @milestone.issue_count
%li
= link_to '#tab-merge-requests', 'data-toggle' => 'tab' do
Merge Requests
- %span.badge= @dashboard_milestone.merge_requests_count
+ %span.badge= @milestone.merge_requests_count
%li
= link_to '#tab-participants', 'data-toggle' => 'tab' do
Participants
- %span.badge= @dashboard_milestone.participants.count
+ %span.badge= @milestone.participants.count
.pull-right
- = link_to 'Browse Issues', issues_dashboard_path(milestone_title: @dashboard_milestone.title), class: "btn edit-milestone-link btn-grouped"
+ = link_to 'Browse Issues', issues_dashboard_path(milestone_title: @milestone.title), class: "btn edit-milestone-link btn-grouped"
.tab-content
.tab-pane.active#tab-issues
.row
.col-md-6
- = render 'issues', title: "Open", issues: @dashboard_milestone.opened_issues
+ = render 'issues', title: "Open", issues: @milestone.opened_issues
.col-md-6
- = render 'issues', title: "Closed", issues: @dashboard_milestone.closed_issues
+ = render 'issues', title: "Closed", issues: @milestone.closed_issues
.tab-pane#tab-merge-requests
.row
.col-md-6
- = render 'merge_requests', title: "Open", merge_requests: @dashboard_milestone.opened_merge_requests
+ = render 'merge_requests', title: "Open", merge_requests: @milestone.opened_merge_requests
.col-md-6
- = render 'merge_requests', title: "Closed", merge_requests: @dashboard_milestone.closed_merge_requests
+ = render 'merge_requests', title: "Closed", merge_requests: @milestone.closed_merge_requests
.tab-pane#tab-participants
%ul.bordered-list
- - @dashboard_milestone.participants.each do |user|
+ - @milestone.participants.each do |user|
%li
= link_to user, title: user.name, class: "darken" do
= image_tag avatar_icon(user, 32), class: "avatar s32"
diff --git a/app/views/dashboard/snippets/index.html.haml b/app/views/dashboard/snippets/index.html.haml
index d3908062f43..07b6d57932e 100644
--- a/app/views/dashboard/snippets/index.html.haml
+++ b/app/views/dashboard/snippets/index.html.haml
@@ -6,33 +6,29 @@
.gray-content-block
.pull-right
= link_to new_snippet_path, class: "btn btn-new", title: "New Snippet" do
- Add new snippet
+ = icon('plus')
+ New Snippet
- .oneline
- Share code pastes with others out of git repository
-
-%ul.nav.nav-tabs.prepend-top-20
- = nav_tab :scope, nil do
- = link_to dashboard_snippets_path do
+ .btn-group.btn-group-next.snippet-scope-menu
+ = link_to dashboard_snippets_path, class: "btn btn-default #{"active" unless params[:scope]}" do
All
%span.badge
= current_user.snippets.count
- = nav_tab :scope, 'are_private' do
- = link_to dashboard_snippets_path(scope: 'are_private') do
+
+ = link_to dashboard_snippets_path(scope: 'are_private'), class: "btn btn-default #{"active" if params[:scope] == "are_private"}" do
Private
%span.badge
= current_user.snippets.are_private.count
- = nav_tab :scope, 'are_internal' do
- = link_to dashboard_snippets_path(scope: 'are_internal') do
+
+ = link_to dashboard_snippets_path(scope: 'are_internal'), class: "btn btn-default #{"active" if params[:scope] == "are_internal"}" do
Internal
%span.badge
= current_user.snippets.are_internal.count
- = nav_tab :scope, 'are_public' do
- = link_to dashboard_snippets_path(scope: 'are_public') do
+
+ = link_to dashboard_snippets_path(scope: 'are_public'), class: "btn btn-default #{"active" if params[:scope] == "are_public"}" do
Public
%span.badge
= current_user.snippets.are_public.count
-.my-snippets
- = render 'snippets/snippets'
+= render 'snippets/snippets'
diff --git a/app/views/doorkeeper/applications/index.html.haml b/app/views/doorkeeper/applications/index.html.haml
index 3b0b19107ca..ba4c5b86efb 100644
--- a/app/views/doorkeeper/applications/index.html.haml
+++ b/app/views/doorkeeper/applications/index.html.haml
@@ -1,17 +1,19 @@
- page_title "Applications"
%h3.page-title Your applications
%p= link_to 'New Application', new_oauth_application_path, class: 'btn btn-success'
-%table.table.table-striped
- %thead
- %tr
- %th Name
- %th Callback URL
- %th
- %th
- %tbody
- - @applications.each do |application|
- %tr{:id => "application_#{application.id}"}
- %td= link_to application.name, oauth_application_path(application)
- %td= application.redirect_uri
- %td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link'
- %td= render 'delete_form', application: application
+
+.table-holder
+ %table.table.table-striped
+ %thead
+ %tr
+ %th Name
+ %th Callback URL
+ %th
+ %th
+ %tbody
+ - @applications.each do |application|
+ %tr{:id => "application_#{application.id}"}
+ %td= link_to application.name, oauth_application_path(application)
+ %td= application.redirect_uri
+ %td= link_to 'Edit', edit_oauth_application_path(application), class: 'btn btn-link'
+ %td= render 'delete_form', application: application
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index 80340aca54c..47442b78d48 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -2,26 +2,26 @@
%h3.page-title
Application: #{@application.name}
+.table-holder
+ %table.table
+ %tr
+ %td
+ Application Id
+ %td
+ %code#application_id= @application.uid
+ %tr
+ %td
+ Secret:
+ %td
+ %code#secret= @application.secret
-%table.table
- %tr
- %td
- Application Id
- %td
- %code#application_id= @application.uid
- %tr
- %td
- Secret:
- %td
- %code#secret= @application.secret
-
- %tr
- %td
- Callback url
- %td
- - @application.redirect_uri.split.each do |uri|
- %div
- %span.monospace= uri
+ %tr
+ %td
+ Callback url
+ %td
+ - @application.redirect_uri.split.each do |uri|
+ %div
+ %span.monospace= uri
.form-actions
= link_to 'Edit', edit_oauth_application_path(@application), class: 'btn btn-primary wide pull-left'
= render 'delete_form', application: @application, submit_btn_css: 'btn btn-danger prepend-left-10'
diff --git a/app/views/doorkeeper/authorized_applications/index.html.haml b/app/views/doorkeeper/authorized_applications/index.html.haml
index 814cdc987ef..b184b9c01d4 100644
--- a/app/views/doorkeeper/authorized_applications/index.html.haml
+++ b/app/views/doorkeeper/authorized_applications/index.html.haml
@@ -1,16 +1,17 @@
%header.page-header
%h1 Your authorized applications
%main{:role => "main"}
- %table.table.table-striped
- %thead
- %tr
- %th Application
- %th Created At
- %th
- %th
- %tbody
- - @applications.each do |application|
+ .table-holder
+ %table.table.table-striped
+ %thead
%tr
- %td= application.name
- %td= application.created_at.strftime('%Y-%m-%d %H:%M:%S')
- %td= render 'delete_form', application: application \ No newline at end of file
+ %th Application
+ %th Created At
+ %th
+ %th
+ %tbody
+ - @applications.each do |application|
+ %tr
+ %td= application.name
+ %td= application.created_at.strftime('%Y-%m-%d %H:%M:%S')
+ %td= render 'delete_form', application: application
diff --git a/app/views/events/_event_issue.atom.haml b/app/views/events/_event_issue.atom.haml
index 4259f64c191..fad65310021 100644
--- a/app/views/events/_event_issue.atom.haml
+++ b/app/views/events/_event_issue.atom.haml
@@ -1,3 +1,2 @@
%div{xmlns: "http://www.w3.org/1999/xhtml"}
- - if issue.description.present?
- = markdown(issue.description, xhtml: true, reference_only_path: false, project: issue.project)
+ = markdown(issue.description, pipeline: :atom, project: issue.project)
diff --git a/app/views/events/_event_merge_request.atom.haml b/app/views/events/_event_merge_request.atom.haml
index e8ed13df783..19bdc7b9ca5 100644
--- a/app/views/events/_event_merge_request.atom.haml
+++ b/app/views/events/_event_merge_request.atom.haml
@@ -1,3 +1,2 @@
%div{xmlns: "http://www.w3.org/1999/xhtml"}
- - if merge_request.description.present?
- = markdown(merge_request.description, xhtml: true, reference_only_path: false, project: merge_request.project)
+ = markdown(merge_request.description, pipeline: :atom, project: merge_request.project)
diff --git a/app/views/events/_event_note.atom.haml b/app/views/events/_event_note.atom.haml
index cfbfba50202..b730ebbd5f9 100644
--- a/app/views/events/_event_note.atom.haml
+++ b/app/views/events/_event_note.atom.haml
@@ -1,2 +1,2 @@
%div{xmlns: "http://www.w3.org/1999/xhtml"}
- = markdown(note.note, xhtml: true, reference_only_path: false, project: note.project)
+ = markdown(note.note, pipeline: :atom, project: note.project)
diff --git a/app/views/events/_event_push.atom.haml b/app/views/events/_event_push.atom.haml
index 3625cb49d8b..b271b9daff1 100644
--- a/app/views/events/_event_push.atom.haml
+++ b/app/views/events/_event_push.atom.haml
@@ -6,7 +6,7 @@
%i
at
= commit[:timestamp].to_time.to_s(:short)
- %blockquote= markdown(escape_once(commit[:message]), xhtml: true, reference_only_path: false, project: event.project)
+ %blockquote= markdown(escape_once(commit[:message]), pipeline: :atom, project: event.project)
- if event.commits_count > 15
%p
%i
diff --git a/app/views/explore/snippets/index.html.haml b/app/views/explore/snippets/index.html.haml
index 7e4fa7d4873..0f100c39ffb 100644
--- a/app/views/explore/snippets/index.html.haml
+++ b/app/views/explore/snippets/index.html.haml
@@ -10,7 +10,8 @@
- if current_user
.pull-right
= link_to new_snippet_path, class: "btn btn-new", title: "New Snippet" do
- Add new snippet
+ = icon('plus')
+ New Snippet
.oneline
Public snippets created by you and other users are listed here
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index ae8fc9f85f0..57308a661c0 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -25,6 +25,15 @@
%hr
= link_to 'Remove avatar', group_avatar_path(@group.to_param), data: { confirm: "Group avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-avatar"
+ .form-group
+ %hr
+ = f.label :public, class: 'control-label' do
+ Public
+ .col-sm-10
+ .checkbox
+ = f.check_box :public
+ %span.descr Make this group public (even if there is no any public project inside this group)
+
.form-actions
= f.submit 'Save group', class: "btn btn-save"
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index fee4b0052b5..15d289471c9 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -36,7 +36,8 @@
= paginate @members, theme: 'gitlab'
-:coffeescript
- $('form.member-search-form').on 'submit', (event) ->
- event.preventDefault()
- Turbolinks.visit @.action + '?' + $(@).serialize()
+:javascript
+ $('form.member-search-form').on('submit', function(event) {
+ event.preventDefault();
+ Turbolinks.visit(this.action + '?' + $(this).serialize());
+ });
diff --git a/app/views/groups/milestones/_milestone.html.haml b/app/views/groups/milestones/_milestone.html.haml
index 41dffdd2fb8..a20bf75bc39 100644
--- a/app/views/groups/milestones/_milestone.html.haml
+++ b/app/views/groups/milestones/_milestone.html.haml
@@ -22,7 +22,7 @@
%span.label.label-gray
= milestone.project.name
.col-sm-6
- - if can?(current_user, :admin_group, @group)
+ - if can?(current_user, :admin_milestones, @group)
- if milestone.closed?
= link_to 'Reopen Milestone', group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-xs btn-grouped btn-reopen"
- else
diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml
index 2bbcad5fdfb..84ec77c6188 100644
--- a/app/views/groups/milestones/index.html.haml
+++ b/app/views/groups/milestones/index.html.haml
@@ -3,15 +3,22 @@
= render 'shared/milestones_filter'
.gray-content-block
- Only milestones from
- %strong #{@group.name}
- group are listed here.
+ - if can?(current_user, :admin_milestones, @group)
+ .pull-right
+ %span.pull-right.hidden-xs
+ = link_to new_group_milestone_path(@group), class: "btn btn-new" do
+ New Milestone
+
+ .oneline
+ Only milestones from
+ %strong #{@group.name}
+ group are listed here.
.milestones
%ul.content-list
- - if @group_milestones.blank?
+ - if @milestones.blank?
%li
.nothing-here-block No milestones to show
- else
- - @group_milestones.each do |milestone|
+ - @milestones.each do |milestone|
= render 'milestone', milestone: milestone
- = paginate @group_milestones, theme: "gitlab"
+ = paginate @milestones, theme: "gitlab"
diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml
new file mode 100644
index 00000000000..800bac4ef02
--- /dev/null
+++ b/app/views/groups/milestones/new.html.haml
@@ -0,0 +1,48 @@
+- page_title "Milestones"
+- header_title group_title(@group, "Milestones", group_milestones_path(@group))
+
+%h3.page-title
+ New Milestone
+
+%p.light
+ This will create milestone in every selected project
+%hr
+
+= form_for @milestone, url: group_milestones_path(@group), html: { class: 'form-horizontal milestone-form gfm-form js-requires-input' } do |f|
+ .row
+ .col-md-6
+ .form-group
+ = f.label :title, "Title", class: "control-label"
+ .col-sm-10
+ = f.text_field :title, maxlength: 255, class: "form-control js-quick-submit", required: true
+ %p.hint Required
+ .form-group.milestone-description
+ = f.label :description, "Description", class: "control-label"
+ .col-sm-10
+ = render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do
+ = render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit'
+ .clearfix
+ .error-alert
+ .form-group
+ = f.label :projects, "Projects", class: "control-label"
+ .col-sm-10
+ = f.collection_select :project_ids, @group.projects, :id, :name,
+ { selected: @group.projects.map(&:id) }, multiple: true, class: 'select2'
+
+ .col-md-6
+ .form-group
+ = f.label :due_date, "Due Date", class: "control-label"
+ .col-sm-10= f.hidden_field :due_date
+ .col-sm-10
+ .datepicker
+
+ .form-actions
+ = f.submit 'Create Milestone', class: "btn-create btn"
+ = link_to "Cancel", group_milestones_path(@group), class: "btn btn-cancel"
+
+
+:javascript
+ $(".datepicker").datepicker({
+ dateFormat: "yy-mm-dd",
+ onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
+ }).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val()));
diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml
index c6cde97c585..d161259e4aa 100644
--- a/app/views/groups/milestones/show.html.haml
+++ b/app/views/groups/milestones/show.html.haml
@@ -1,90 +1,92 @@
-- page_title @group_milestone.title, "Milestones"
+- page_title @milestone.title, "Milestones"
= render "header_title"
%h4.page-title
- .issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" }
- - if @group_milestone.closed?
+ .issue-box{ class: "issue-box-#{@milestone.closed? ? 'closed' : 'open'}" }
+ - if @milestone.closed?
Closed
- else
Open
- Milestone #{@group_milestone.title}
+ Milestone #{@milestone.title}
.pull-right
- - if can?(current_user, :admin_group, @group)
- - if @group_milestone.active?
- = link_to 'Close Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close"
+ - if can?(current_user, :admin_milestones, @group)
+ - if @milestone.active?
+ = link_to 'Close Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :close }), method: :put, class: "btn btn-sm btn-close"
- else
- = link_to 'Reopen Milestone', group_milestone_path(@group, @group_milestone.safe_title, title: @group_milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen"
+ = link_to 'Reopen Milestone', group_milestone_path(@group, @milestone.safe_title, title: @milestone.title, milestone: {state_event: :activate }), method: :put, class: "btn btn-sm btn-grouped btn-reopen"
%hr
-- if (@group_milestone.total_items_count == @group_milestone.closed_items_count) && @group_milestone.active?
+- if @milestone.complete? && @milestone.active?
.alert.alert-success
%span All issues for this milestone are closed. You may close the milestone now.
.description
-%table.table
- %thead
- %tr
- %th Project
- %th Open issues
- %th State
- %th Due date
- - @group_milestone.milestones.each do |milestone|
- %tr
- %td
- = link_to "#{milestone.project.name}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
- %td
- = milestone.issues.opened.count
- %td
- - if milestone.closed?
- Closed
- - else
- Open
- %td
- = milestone.expires_at
+
+.table-holder
+ %table.table
+ %thead
+ %tr
+ %th Project
+ %th Open issues
+ %th State
+ %th Due date
+ - @milestone.milestones.each do |milestone|
+ %tr
+ %td
+ = link_to "#{milestone.project.name}", namespace_project_milestone_path(milestone.project.namespace, milestone.project, milestone)
+ %td
+ = milestone.issues.opened.count
+ %td
+ - if milestone.closed?
+ Closed
+ - else
+ Open
+ %td
+ = milestone.expires_at
.context
%p.lead
Progress:
- #{@group_milestone.closed_items_count} closed
+ #{@milestone.closed_items_count} closed
&ndash;
- #{@group_milestone.open_items_count} open
- = milestone_progress_bar(@group_milestone)
+ #{@milestone.open_items_count} open
+ = milestone_progress_bar(@milestone)
%ul.nav.nav-tabs
%li.active
= link_to '#tab-issues', 'data-toggle' => 'tab' do
Issues
- %span.badge= @group_milestone.issue_count
+ %span.badge= @milestone.issue_count
%li
= link_to '#tab-merge-requests', 'data-toggle' => 'tab' do
Merge Requests
- %span.badge= @group_milestone.merge_requests_count
+ %span.badge= @milestone.merge_requests_count
%li
= link_to '#tab-participants', 'data-toggle' => 'tab' do
Participants
- %span.badge= @group_milestone.participants.count
+ %span.badge= @milestone.participants.count
.pull-right
- = link_to 'Browse Issues', issues_group_path(@group, milestone_title: @group_milestone.title), class: "btn edit-milestone-link btn-grouped"
+ = link_to 'Browse Issues', issues_group_path(@group, milestone_title: @milestone.title), class: "btn edit-milestone-link btn-grouped"
.tab-content
.tab-pane.active#tab-issues
.row
.col-md-6
- = render 'issues', title: "Open", issues: @group_milestone.opened_issues
+ = render 'issues', title: "Open", issues: @milestone.opened_issues
.col-md-6
- = render 'issues', title: "Closed", issues: @group_milestone.closed_issues
+ = render 'issues', title: "Closed", issues: @milestone.closed_issues
.tab-pane#tab-merge-requests
.row
.col-md-6
- = render 'merge_requests', title: "Open", merge_requests: @group_milestone.opened_merge_requests
+ = render 'merge_requests', title: "Open", merge_requests: @milestone.opened_merge_requests
.col-md-6
- = render 'merge_requests', title: "Closed", merge_requests: @group_milestone.closed_merge_requests
+ = render 'merge_requests', title: "Closed", merge_requests: @milestone.closed_merge_requests
.tab-pane#tab-participants
%ul.bordered-list
- - @group_milestone.participants.each do |user|
+ - @milestone.participants.each do |user|
%li
= link_to user, title: user.name, class: "darken" do
= image_tag avatar_icon(user, 32), class: "avatar s32"
diff --git a/app/views/help/_shortcuts.html.haml b/app/views/help/_shortcuts.html.haml
index 67349fcbd78..7e801b5332d 100644
--- a/app/views/help/_shortcuts.html.haml
+++ b/app/views/help/_shortcuts.html.haml
@@ -222,8 +222,8 @@
:javascript
- $('.js-more-help-button').click(function(e){
- $(this).remove()
- $('.hidden-shortcut').show()
- e.preventDefault()
+ $('.js-more-help-button').click(function (e) {
+ $(this).remove()l
+ $('.hidden-shortcut').show();
+ e.preventDefault();
});
diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml
index 777eb482714..1f09a27e2d6 100644
--- a/app/views/import/bitbucket/status.html.haml
+++ b/app/views/import/bitbucket/status.html.haml
@@ -14,45 +14,46 @@
= button_tag 'Import all projects', class: "btn btn-success js-import-all"
-%table.table.import-jobs
- %thead
- %tr
- %th From Bitbucket
- %th To GitLab
- %th Status
- %tbody
- - @already_added_projects.each do |project|
- %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
- %td
- = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: "_blank"
- %td
- %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
- %td.job-status
- - if project.import_status == 'finished'
- %span
- %i.fa.fa-check
- done
- - elsif project.import_status == 'started'
- %i.fa.fa-spinner.fa-spin
- started
- - else
- = project.human_import_status_name
+.table-holder
+ %table.table.import-jobs
+ %thead
+ %tr
+ %th From Bitbucket
+ %th To GitLab
+ %th Status
+ %tbody
+ - @already_added_projects.each do |project|
+ %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+ %td
+ = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: "_blank"
+ %td
+ %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+ %td.job-status
+ - if project.import_status == 'finished'
+ %span
+ %i.fa.fa-check
+ done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
+ - else
+ = project.human_import_status_name
- - @repos.each do |repo|
- %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"}
- %td
- = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank"
- %td.import-target
- = "#{repo["owner"]}/#{repo["slug"]}"
- %td.import-actions.job-status
- = button_tag "Import", class: "btn js-add-to-import"
- - @incompatible_repos.each do |repo|
- %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"}
- %td
- = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank"
- %td.import-target
- %td.import-actions-job-status
- = label_tag "Incompatible Project", nil, class: "label label-danger"
+ - @repos.each do |repo|
+ %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"}
+ %td
+ = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank"
+ %td.import-target
+ = "#{repo["owner"]}/#{repo["slug"]}"
+ %td.import-actions.job-status
+ = button_tag "Import", class: "btn js-add-to-import"
+ - @incompatible_repos.each do |repo|
+ %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"}
+ %td
+ = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank"
+ %td.import-target
+ %td.import-actions-job-status
+ = label_tag "Incompatible Project", nil, class: "label label-danger"
- if @incompatible_repos.any?
%p
@@ -65,5 +66,5 @@
again.
-:coffeescript
- new ImporterStatus("#{jobs_import_bitbucket_path}", "#{import_bitbucket_path}")
+:javascript
+ new ImporterStatus("#{jobs_import_bitbucket_path}", "#{import_bitbucket_path}");
diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml
index 25cebfb3665..bc3c90294e3 100644
--- a/app/views/import/fogbugz/new_user_map.html.haml
+++ b/app/views/import/fogbugz/new_user_map.html.haml
@@ -22,28 +22,29 @@
%strong Map a FogBugz account ID to a GitLab user
%p
Selecting a GitLab user will add a link to the GitLab user in the descriptions
- of issues and comments (e.g. "By <a href="#">@johnsmith</a>"). It will also
+ of issues and comments (e.g. "By <a href="#">@johnsmith</a>"). It will also
associate and/or assign these issues and comments with the selected user.
- %table.table
- %thead
- %tr
- %th ID
- %th Name
- %th Email
- %th GitLab User
- %tbody
- - @user_map.each do |id, user|
+ .table-holder
+ %table.table
+ %thead
%tr
- %td= id
- %td= text_field_tag "users[#{id}][name]", user[:name], class: 'form-control'
- %td= text_field_tag "users[#{id}][email]", user[:email], class: 'form-control'
- %td
- = users_select_tag("users[#{id}][gitlab_user]", class: 'custom-form-control',
- scope: :all, email_user: true, selected: user[:gitlab_user])
+ %th ID
+ %th Name
+ %th Email
+ %th GitLab User
+ %tbody
+ - @user_map.each do |id, user|
+ %tr
+ %td= id
+ %td= text_field_tag "users[#{id}][name]", user[:name], class: 'form-control'
+ %td= text_field_tag "users[#{id}][email]", user[:email], class: 'form-control'
+ %td
+ = users_select_tag("users[#{id}][gitlab_user]", class: 'custom-form-control',
+ scope: :all, email_user: true, selected: user[:gitlab_user])
.form-actions
= submit_tag 'Continue to the next step', class: 'btn btn-create'
-:coffeescript
- new UsersSelect()
+:javascript
+ new UsersSelect();
diff --git a/app/views/import/fogbugz/status.html.haml b/app/views/import/fogbugz/status.html.haml
index f179ece402d..b902006597b 100644
--- a/app/views/import/fogbugz/status.html.haml
+++ b/app/views/import/fogbugz/status.html.haml
@@ -14,38 +14,39 @@
%p
= button_tag 'Import all projects', class: 'btn btn-success js-import-all'
-%table.table.import-jobs
- %thead
- %tr
- %th From FogBugz
- %th To GitLab
- %th Status
- %tbody
- - @already_added_projects.each do |project|
- %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
- %td
- = project.import_source
- %td
- %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
- %td.job-status
- - if project.import_status == 'finished'
- %span
- %i.fa.fa-check
- done
- - elsif project.import_status == 'started'
- %i.fa.fa-spinner.fa-spin
- started
- - else
- = project.human_import_status_name
+.table-holder
+ %table.table.import-jobs
+ %thead
+ %tr
+ %th From FogBugz
+ %th To GitLab
+ %th Status
+ %tbody
+ - @already_added_projects.each do |project|
+ %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+ %td
+ = project.import_source
+ %td
+ %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+ %td.job-status
+ - if project.import_status == 'finished'
+ %span
+ %i.fa.fa-check
+ done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
+ - else
+ = project.human_import_status_name
- - @repos.each do |repo|
- %tr{id: "repo_#{repo.id}"}
- %td
- = repo.name
- %td.import-target
- = "#{current_user.username}/#{repo.name}"
- %td.import-actions.job-status
- = button_tag "Import", class: "btn js-add-to-import"
+ - @repos.each do |repo|
+ %tr{id: "repo_#{repo.id}"}
+ %td
+ = repo.name
+ %td.import-target
+ = "#{current_user.username}/#{repo.name}"
+ %td.import-actions.job-status
+ = button_tag "Import", class: "btn js-add-to-import"
-:coffeescript
- new ImporterStatus("#{jobs_import_fogbugz_path}", "#{import_fogbugz_path}")
+:javascript
+ new ImporterStatus("#{jobs_import_fogbugz_path}", "#{import_fogbugz_path}");
diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml
index ef552498239..0699321c8c0 100644
--- a/app/views/import/github/status.html.haml
+++ b/app/views/import/github/status.html.haml
@@ -9,38 +9,39 @@
%p
= button_tag 'Import all projects', class: "btn btn-success js-import-all"
-%table.table.import-jobs
- %thead
- %tr
- %th From GitHub
- %th To GitLab
- %th Status
- %tbody
- - @already_added_projects.each do |project|
- %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
- %td
- = link_to project.import_source, "https://github.com/#{project.import_source}", target: "_blank"
- %td
- %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
- %td.job-status
- - if project.import_status == 'finished'
- %span
- %i.fa.fa-check
- done
- - elsif project.import_status == 'started'
- %i.fa.fa-spinner.fa-spin
- started
- - else
- = project.human_import_status_name
+.table-holder
+ %table.table.import-jobs
+ %thead
+ %tr
+ %th From GitHub
+ %th To GitLab
+ %th Status
+ %tbody
+ - @already_added_projects.each do |project|
+ %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+ %td
+ = link_to project.import_source, "https://github.com/#{project.import_source}", target: "_blank"
+ %td
+ %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+ %td.job-status
+ - if project.import_status == 'finished'
+ %span
+ %i.fa.fa-check
+ done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
+ - else
+ = project.human_import_status_name
- - @repos.each do |repo|
- %tr{id: "repo_#{repo.id}"}
- %td
- = link_to repo.full_name, "https://github.com/#{repo.full_name}", target: "_blank"
- %td.import-target
- = repo.full_name
- %td.import-actions.job-status
- = button_tag "Import", class: "btn js-add-to-import"
+ - @repos.each do |repo|
+ %tr{id: "repo_#{repo.id}"}
+ %td
+ = link_to repo.full_name, "https://github.com/#{repo.full_name}", target: "_blank"
+ %td.import-target
+ = repo.full_name
+ %td.import-actions.job-status
+ = button_tag "Import", class: "btn js-add-to-import"
-:coffeescript
- new ImporterStatus("#{jobs_import_github_path}", "#{import_github_path}")
+:javascript
+ new ImporterStatus("#{jobs_import_github_path}", "#{import_github_path}");
diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml
index 727f3c7e7fa..f4a2b33af21 100644
--- a/app/views/import/gitlab/status.html.haml
+++ b/app/views/import/gitlab/status.html.haml
@@ -9,38 +9,39 @@
%p
= button_tag 'Import all projects', class: "btn btn-success js-import-all"
-%table.table.import-jobs
- %thead
- %tr
- %th From GitLab.com
- %th To this GitLab instance
- %th Status
- %tbody
- - @already_added_projects.each do |project|
- %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
- %td
- = link_to project.import_source, "https://gitlab.com/#{project.import_source}", target: "_blank"
- %td
- %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
- %td.job-status
- - if project.import_status == 'finished'
- %span
- %i.fa.fa-check
- done
- - elsif project.import_status == 'started'
- %i.fa.fa-spinner.fa-spin
- started
- - else
- = project.human_import_status_name
+.table-holder
+ %table.table.import-jobs
+ %thead
+ %tr
+ %th From GitLab.com
+ %th To this GitLab instance
+ %th Status
+ %tbody
+ - @already_added_projects.each do |project|
+ %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+ %td
+ = link_to project.import_source, "https://gitlab.com/#{project.import_source}", target: "_blank"
+ %td
+ %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+ %td.job-status
+ - if project.import_status == 'finished'
+ %span
+ %i.fa.fa-check
+ done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
+ - else
+ = project.human_import_status_name
- - @repos.each do |repo|
- %tr{id: "repo_#{repo["id"]}"}
- %td
- = link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank"
- %td.import-target
- = repo["path_with_namespace"]
- %td.import-actions.job-status
- = button_tag "Import", class: "btn js-add-to-import"
+ - @repos.each do |repo|
+ %tr{id: "repo_#{repo["id"]}"}
+ %td
+ = link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank"
+ %td.import-target
+ = repo["path_with_namespace"]
+ %td.import-actions.job-status
+ = button_tag "Import", class: "btn js-add-to-import"
-:coffeescript
- new ImporterStatus("#{jobs_import_gitlab_path}", "#{import_gitlab_path}")
+:javascript
+ new ImporterStatus("#{jobs_import_gitlab_path}", "#{import_gitlab_path}");
diff --git a/app/views/import/gitorious/status.html.haml b/app/views/import/gitorious/status.html.haml
index bff7ee7c85d..71752d21efa 100644
--- a/app/views/import/gitorious/status.html.haml
+++ b/app/views/import/gitorious/status.html.haml
@@ -9,38 +9,39 @@
%p
= button_tag 'Import all projects', class: "btn btn-success js-import-all"
-%table.table.import-jobs
- %thead
- %tr
- %th From Gitorious.org
- %th To GitLab
- %th Status
- %tbody
- - @already_added_projects.each do |project|
- %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
- %td
- = link_to project.import_source, "https://gitorious.org/#{project.import_source}", target: "_blank"
- %td
- %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
- %td.job-status
- - if project.import_status == 'finished'
- %span
- %i.fa.fa-check
- done
- - elsif project.import_status == 'started'
- %i.fa.fa-spinner.fa-spin
- started
- - else
- = project.human_import_status_name
+.table-holder
+ %table.table.import-jobs
+ %thead
+ %tr
+ %th From Gitorious.org
+ %th To GitLab
+ %th Status
+ %tbody
+ - @already_added_projects.each do |project|
+ %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+ %td
+ = link_to project.import_source, "https://gitorious.org/#{project.import_source}", target: "_blank"
+ %td
+ %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+ %td.job-status
+ - if project.import_status == 'finished'
+ %span
+ %i.fa.fa-check
+ done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
+ - else
+ = project.human_import_status_name
- - @repos.each do |repo|
- %tr{id: "repo_#{repo.id}"}
- %td
- = link_to repo.full_name, "https://gitorious.org/#{repo.full_name}", target: "_blank"
- %td.import-target
- = repo.full_name
- %td.import-actions.job-status
- = button_tag "Import", class: "btn js-add-to-import"
+ - @repos.each do |repo|
+ %tr{id: "repo_#{repo.id}"}
+ %td
+ = link_to repo.full_name, "https://gitorious.org/#{repo.full_name}", target: "_blank"
+ %td.import-target
+ = repo.full_name
+ %td.import-actions.job-status
+ = button_tag "Import", class: "btn js-add-to-import"
-:coffeescript
- new ImporterStatus("#{jobs_import_gitorious_path}", "#{import_gitorious_path}")
+:javascript
+ new ImporterStatus("#{jobs_import_gitorious_path}", "#{import_gitorious_path}");
diff --git a/app/views/import/google_code/status.html.haml b/app/views/import/google_code/status.html.haml
index e8ec79e72f7..8c64fd27e60 100644
--- a/app/views/import/google_code/status.html.haml
+++ b/app/views/import/google_code/status.html.haml
@@ -17,45 +17,46 @@
- else
= button_tag 'Import all projects', class: "btn btn-success js-import-all"
-%table.table.import-jobs
- %thead
- %tr
- %th From Google Code
- %th To GitLab
- %th Status
- %tbody
- - @already_added_projects.each do |project|
- %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
- %td
- = link_to project.import_source, "https://code.google.com/p/#{project.import_source}", target: "_blank"
- %td
- %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
- %td.job-status
- - if project.import_status == 'finished'
- %span
- %i.fa.fa-check
- done
- - elsif project.import_status == 'started'
- %i.fa.fa-spinner.fa-spin
- started
- - else
- = project.human_import_status_name
+.table-holder
+ %table.table.import-jobs
+ %thead
+ %tr
+ %th From Google Code
+ %th To GitLab
+ %th Status
+ %tbody
+ - @already_added_projects.each do |project|
+ %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+ %td
+ = link_to project.import_source, "https://code.google.com/p/#{project.import_source}", target: "_blank"
+ %td
+ %strong= link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
+ %td.job-status
+ - if project.import_status == 'finished'
+ %span
+ %i.fa.fa-check
+ done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
+ - else
+ = project.human_import_status_name
- - @repos.each do |repo|
- %tr{id: "repo_#{repo.id}"}
- %td
- = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank"
- %td.import-target
- = "#{current_user.username}/#{repo.name}"
- %td.import-actions.job-status
- = button_tag "Import", class: "btn js-add-to-import"
- - @incompatible_repos.each do |repo|
- %tr{id: "repo_#{repo.id}"}
- %td
- = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank"
- %td.import-target
- %td.import-actions-job-status
- = label_tag "Incompatible Project", nil, class: "label label-danger"
+ - @repos.each do |repo|
+ %tr{id: "repo_#{repo.id}"}
+ %td
+ = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank"
+ %td.import-target
+ = "#{current_user.username}/#{repo.name}"
+ %td.import-actions.job-status
+ = button_tag "Import", class: "btn js-add-to-import"
+ - @incompatible_repos.each do |repo|
+ %tr{id: "repo_#{repo.id}"}
+ %td
+ = link_to repo.name, "https://code.google.com/p/#{repo.name}", target: "_blank"
+ %td.import-target
+ %td.import-actions-job-status
+ = label_tag "Incompatible Project", nil, class: "label label-danger"
- if @incompatible_repos.any?
%p
@@ -66,5 +67,5 @@
= link_to "import flow", new_import_google_code_path
again.
-:coffeescript
- new ImporterStatus("#{jobs_import_google_code_path}", "#{import_google_code_path}")
+:javascript
+ new ImporterStatus("#{jobs_import_google_code_path}", "#{import_google_code_path}");
diff --git a/app/views/layouts/_piwik.html.haml b/app/views/layouts/_piwik.html.haml
index 135e8daca26..259b4f7cdfc 100644
--- a/app/views/layouts/_piwik.html.haml
+++ b/app/views/layouts/_piwik.html.haml
@@ -1,12 +1,14 @@
+<!-- Piwik -->
:javascript
var _paq = _paq || [];
- _paq.push(["trackPageView"]);
- _paq.push(["enableLinkTracking"]);
-
+ _paq.push(['trackPageView']);
+ _paq.push(['enableLinkTracking']);
(function() {
- var u=(("https:" == document.location.protocol) ? "https" : "http") + "://#{extra_config.piwik_url}/";
- _paq.push(["setTrackerUrl", u+"piwik.php"]);
- _paq.push(["setSiteId", "#{extra_config.piwik_site_id}"]);
- var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0]; g.type="text/javascript";
- g.defer=true; g.async=true; g.src=u+"piwik.js"; s.parentNode.insertBefore(g,s);
+ var u="//#{extra_config.piwik_url}/";
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
+ _paq.push(['setSiteId', #{extra_config.piwik_site_id}]);
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+ g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
+<noscript><p><img src="//#{extra_config.piwik_url}/piwik.php?idsite=#{extra_config.piwik_site_id}" style="border:0;" alt="" /></p></noscript>
+<!-- End Piwik Code -->
diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml
index ceb64ce3157..a44f5762a6b 100644
--- a/app/views/layouts/_search.html.haml
+++ b/app/views/layouts/_search.html.haml
@@ -11,6 +11,8 @@
= hidden_field_tag :scope, 'merge_requests'
- elsif current_controller?(:wikis)
= hidden_field_tag :scope, 'wiki_blobs'
+ - elsif current_controller?(:commits)
+ = hidden_field_tag :scope, 'commits'
- else
= hidden_field_tag :search_code, true
@@ -23,6 +25,6 @@
:javascript
$('.search-input').on('keyup', function(e) {
if (e.keyCode == 27) {
- $('.search-input').blur()
+ $('.search-input').blur();
}
- })
+ });
diff --git a/app/views/layouts/ci/_nav_admin.html.haml b/app/views/layouts/ci/_nav_admin.html.haml
index af2545a22d8..dcda04a4638 100644
--- a/app/views/layouts/ci/_nav_admin.html.haml
+++ b/app/views/layouts/ci/_nav_admin.html.haml
@@ -9,23 +9,25 @@
= nav_link path: 'projects#index' do
= link_to ci_admin_projects_path do
= icon('list-alt fw')
- Projects
+ %span
+ Projects
= nav_link path: 'events#index' do
= link_to ci_admin_events_path do
= icon('book fw')
- Events
+ %span
+ Events
= nav_link path: ['runners#index', 'runners#show'] do
= link_to ci_admin_runners_path do
= icon('cog fw')
- Runners
- %small.pull-right
- = Ci::Runner.count(:all)
+ %span
+ Runners
+ %span.count= Ci::Runner.count(:all)
= nav_link path: 'builds#index' do
= link_to ci_admin_builds_path do
= icon('link fw')
- Builds
- %small.pull-right
- = Ci::Build.count(:all)
+ %span
+ Builds
+ %span.count= Ci::Build.count(:all)
= nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do
= link_to ci_admin_application_settings_path do
= icon('cogs fw')
diff --git a/app/views/layouts/ci/project.html.haml b/app/views/layouts/ci/project.html.haml
deleted file mode 100644
index 15478c3f5bc..00000000000
--- a/app/views/layouts/ci/project.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-!!! 5
-%html{ lang: "en"}
- = render 'layouts/head'
- %body{class: "ci-body #{user_application_theme}", 'data-page' => body_data_page}
- - header_title @project.name, ci_project_path(@project)
- - if current_user
- = render "layouts/header/default", title: header_title
- - else
- = render "layouts/header/public", title: header_title
-
- = render 'layouts/ci/page', sidebar: 'nav_project'
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index c31b1cbe9a8..3ca30d3baab 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -13,6 +13,10 @@
%li.visible-sm.visible-xs
= link_to search_path, title: 'Search', data: {toggle: 'tooltip', placement: 'bottom'} do
= icon('search')
+ - if session[:impersonator_id]
+ %li.impersonation
+ = link_to stop_impersonation_admin_users_path, method: :delete, title: 'Stop impersonation', data: { toggle: 'tooltip', placement: 'bottom' } do
+ = icon('user-secret fw')
- if current_user.is_admin?
%li
= link_to admin_root_path, title: 'Admin area', data: {toggle: 'tooltip', placement: 'bottom'} do
@@ -21,6 +25,11 @@
%li
= link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom'} do
= icon('plus fw')
+ - if Gitlab::Sherlock.enabled?
+ %li
+ = link_to sherlock_transactions_path, title: 'Sherlock Transactions',
+ data: {toggle: 'tooltip', placement: 'bottom'} do
+ = icon('tachometer fw')
%li
= link_to destroy_user_session_path, class: 'logout', method: :delete, title: 'Sign out', data: {toggle: 'tooltip', placement: 'bottom'} do
= icon('sign-out')
diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml
index eb35af22b93..319352876b4 100644
--- a/app/views/layouts/nav/_group.html.haml
+++ b/app/views/layouts/nav/_group.html.haml
@@ -1,9 +1,9 @@
%ul.nav.nav-sidebar
= nav_link do
- = link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do
+ = link_to root_path, title: 'Go to dashboard', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
- Back to dashboard
+ Go to dashboard
%li.separate-item
diff --git a/app/views/layouts/nav/_group_settings.html.haml b/app/views/layouts/nav/_group_settings.html.haml
index 8075fe32fbc..c8411521f36 100644
--- a/app/views/layouts/nav/_group_settings.html.haml
+++ b/app/views/layouts/nav/_group_settings.html.haml
@@ -1,9 +1,9 @@
%ul.nav.nav-sidebar
= nav_link do
- = link_to group_path(@group), title: 'Back to group', data: {placement: 'right'}, class: 'back-link' do
+ = link_to group_path(@group), title: 'Go to group', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
- Back to group
+ Go to group
%li.separate-item
diff --git a/app/views/layouts/nav/_profile.html.haml b/app/views/layouts/nav/_profile.html.haml
index 5a47b8e6db2..0f3a793e30b 100644
--- a/app/views/layouts/nav/_profile.html.haml
+++ b/app/views/layouts/nav/_profile.html.haml
@@ -1,9 +1,9 @@
%ul.nav.nav-sidebar
= nav_link do
- = link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do
+ = link_to root_path, title: 'Go to dashboard', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
- Back to dashboard
+ Go to dashboard
%li.separate-item
diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml
index 53a913fe8f3..2b91d7721f9 100644
--- a/app/views/layouts/nav/_project.html.haml
+++ b/app/views/layouts/nav/_project.html.haml
@@ -1,16 +1,16 @@
%ul.nav.nav-sidebar
- if @project.group
= nav_link do
- = link_to group_path(@project.group), title: 'Back to group', data: {placement: 'right'}, class: 'back-link' do
+ = link_to group_path(@project.group), title: 'Go to group', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
- Back to group
+ Go to group
- else
= nav_link do
- = link_to root_path, title: 'Back to dashboard', data: {placement: 'right'}, class: 'back-link' do
+ = link_to root_path, title: 'Go to dashboard', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
- Back to dashboard
+ Go to dashboard
%li.separate-item
@@ -32,7 +32,7 @@
Files
- if project_nav_tab? :commits
- = nav_link(controller: %w(commit commits compare repositories tags branches)) do
+ = nav_link(controller: %w(commit commits compare repositories tags branches releases)) do
= link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do
= icon('history fw')
%span
diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml
index 954dbe5d2b9..377a99e719a 100644
--- a/app/views/layouts/nav/_project_settings.html.haml
+++ b/app/views/layouts/nav/_project_settings.html.haml
@@ -1,9 +1,9 @@
%ul.nav.nav-sidebar
= nav_link do
- = link_to project_path(@project), title: 'Back to project', data: {placement: 'right'}, class: 'back-link' do
+ = link_to project_path(@project), title: 'Go to project', data: {placement: 'right'}, class: 'back-link' do
= icon('caret-square-o-left fw')
%span
- Back to project
+ Go to project
%li.separate-item
@@ -34,7 +34,7 @@
%span
Protected Branches
- - if @project.gitlab_ci?
+ - if @project.builds_enabled?
= nav_link(controller: :runners) do
= link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners', data: {placement: 'right'} do
= icon('cog fw')
@@ -65,8 +65,3 @@
= icon('share fw')
%span
CI Services
- = nav_link path: 'events#index' do
- = link_to ci_project_events_path(@project.gitlab_ci_project) do
- = icon('book fw')
- %span
- CI Events
diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml
index 2f7d7e86f56..3ca4c340406 100644
--- a/app/views/layouts/notify.html.haml
+++ b/app/views/layouts/notify.html.haml
@@ -40,5 +40,10 @@
Reply to this email directly or
#{link_to "view it on GitLab", @target_url}.
- else
- #{link_to "View it on GitLab", @target_url}
- = email_action @target_url
+ #{link_to "View it on GitLab", @target_url}.
+ %br
+ -# Don't link the host is the line below, one link in the email is easier to quickly click than two.
+ You're receiving this email because of your account on #{Gitlab.config.gitlab.host}.
+ If you'd like to receive fewer emails, you can adjust your notification settings.
+
+ = email_action @target_url \ No newline at end of file
diff --git a/app/views/notify/_note_message.html.haml b/app/views/notify/_note_message.html.haml
index 3fd4b04ac84..00cb4aa24cc 100644
--- a/app/views/notify/_note_message.html.haml
+++ b/app/views/notify/_note_message.html.haml
@@ -1,2 +1,2 @@
%div
- = markdown(@note.note, reference_only_path: false)
+ = markdown(@note.note, pipeline: :email)
diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml
index 53a068be52e..d3b799fca23 100644
--- a/app/views/notify/new_issue_email.html.haml
+++ b/app/views/notify/new_issue_email.html.haml
@@ -1,5 +1,5 @@
-if @issue.description
- = markdown(@issue.description, reference_only_path: false)
+ = markdown(@issue.description, pipeline: :email)
- if @issue.assignee_id.present?
%p
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index 5b7dd117c16..90ebdfc3fe2 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -6,4 +6,4 @@
Assignee: #{@merge_request.author_name} &rarr; #{@merge_request.assignee_name}
-if @merge_request.description
- = markdown(@merge_request.description, reference_only_path: false)
+ = markdown(@merge_request.description, pipeline: :email)
diff --git a/app/views/notify/project_was_moved_email.text.erb b/app/views/notify/project_was_moved_email.text.erb
index d8a23dabf49..b2c5f71e465 100644
--- a/app/views/notify/project_was_moved_email.text.erb
+++ b/app/views/notify/project_was_moved_email.text.erb
@@ -1,4 +1,4 @@
-Project #{@old_path_with_namespace} was moved to another location
+Project <%= @old_path_with_namespace %> was moved to another location
The project is now located under
<%= namespace_project_url(@project.namespace, @project) %>
diff --git a/app/views/profiles/_event_table.html.haml b/app/views/profiles/_event_table.html.haml
index c19ac429d52..58af79716a7 100644
--- a/app/views/profiles/_event_table.html.haml
+++ b/app/views/profiles/_event_table.html.haml
@@ -1,16 +1,17 @@
-%table.table#audits
- %thead
- %tr
- %th Action
- %th When
-
- %tbody
- - events.each do |event|
+.table-holder
+ %table.table#audits
+ %thead
%tr
- %td
- %span
- Signed in with
- %b= event.details[:with]
- authentication
- %td #{time_ago_in_words event.created_at} ago
+ %th Action
+ %th When
+
+ %tbody
+ - events.each do |event|
+ %tr
+ %td
+ %span
+ Signed in with
+ %b= event.details[:with]
+ authentication
+ %td #{time_ago_in_words event.created_at} ago
= paginate events, theme: "gitlab"
diff --git a/app/views/profiles/notifications/_settings.html.haml b/app/views/profiles/notifications/_settings.html.haml
index 2c85d2a9b2b..742c5c4b68d 100644
--- a/app/views/profiles/notifications/_settings.html.haml
+++ b/app/views/profiles/notifications/_settings.html.haml
@@ -14,4 +14,4 @@
= form_tag profile_notifications_path, method: :put, remote: true, class: 'update-notifications' do
= hidden_field_tag :notification_type, type, id: dom_id(membership, 'notification_type')
= hidden_field_tag :notification_id, membership.id, id: dom_id(membership, 'notification_id')
- = select_tag :notification_level, options_for_select(Notification.options_with_labels, notification.level), class: 'trigger-submit'
+ = select_tag :notification_level, options_for_select(Notification.options_with_labels, notification.level), class: 'form-control trigger-submit'
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 01e285a8dfa..cc41d7dd813 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -38,7 +38,7 @@
.col-sm-10
= f.select :layout, layout_choices, {}, class: 'form-control'
.help-block
- Choose between fixed (max. 1200px) and fluid (100%) application layout
+ Choose between fixed (max. 1200px) and fluid (100%) application layout.
.form-group
= f.label :dashboard, class: 'control-label' do
Default Dashboard
@@ -52,6 +52,6 @@
.col-sm-10
= f.select :project_view, project_view_choices, {}, class: 'form-control'
.help-block
- Choose what content you want to see when visit project page
+ Choose what content you want to see on a project's home page.
.panel-footer
= f.submit 'Save', class: 'btn btn-save'
diff --git a/app/views/projects/_activity.html.haml b/app/views/projects/_activity.html.haml
index c2683bc6219..101880bd105 100644
--- a/app/views/projects/_activity.html.haml
+++ b/app/views/projects/_activity.html.haml
@@ -1,4 +1,3 @@
-= render 'projects/last_push'
.gray-content-block.activity-filter-block
- if current_user
.pull-right
@@ -9,5 +8,5 @@
.content_list{:"data-href" => activity_project_path(@project)}
= spinner
-:coffeescript
- new Activities()
+:javascript
+ new Activities();
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
new file mode 100644
index 00000000000..fa978325ddd
--- /dev/null
+++ b/app/views/projects/_files.html.haml
@@ -0,0 +1,6 @@
+#tree-holder.tree-holder.clearfix
+ .gray-content-block.second-block
+ = render 'projects/tree/tree_header', tree: @tree
+
+ = render 'projects/tree/tree_content', tree: @tree
+
diff --git a/app/views/projects/_last_commit.html.haml b/app/views/projects/_last_commit.html.haml
new file mode 100644
index 00000000000..7e1ee2b7fc1
--- /dev/null
+++ b/app/views/projects/_last_commit.html.haml
@@ -0,0 +1,12 @@
+.project-last-commit
+ - ci_commit = project.ci_commit(commit.sha)
+ - if ci_commit
+ = link_to ci_status_path(ci_commit), class: "ci-status ci-#{ci_commit.status}" do
+ = ci_status_icon(ci_commit)
+ = ci_commit.status
+
+ = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
+ = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit), class: "commit-row-message"
+ &middot;
+ #{time_ago_with_tooltip(commit.committed_date, skip_js: true)} by
+ = commit_author_link(commit, avatar: true, size: 24)
diff --git a/app/views/projects/_readme.html.haml b/app/views/projects/_readme.html.haml
index 5bc1999ec9d..b5ef0aca540 100644
--- a/app/views/projects/_readme.html.haml
+++ b/app/views/projects/_readme.html.haml
@@ -1,12 +1,9 @@
- if readme = @repository.readme
- %article.readme-holder#README
- .clearfix
- .pull-right
- &nbsp;
- - if can?(current_user, :push_code, @project)
- = link_to namespace_project_edit_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)), class: 'light' do
- %i.fa-align.fa.fa-pencil
- .wiki
+ %article.readme-holder
+ .pull-right
+ - if can?(current_user, :push_code, @project)
+ = link_to icon('pencil'), namespace_project_edit_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)), class: 'light edit-project-readme'
+ .file-content.wiki
= cache(readme_cache_key) do
= render_readme(readme)
- else
diff --git a/app/views/projects/activity.html.haml b/app/views/projects/activity.html.haml
index 555ed76426d..69fa4ad37c4 100644
--- a/app/views/projects/activity.html.haml
+++ b/app/views/projects/activity.html.haml
@@ -1,4 +1,6 @@
- page_title "Activity"
- header_title project_title(@project, "Activity", activity_project_path(@project))
+= render 'projects/last_push'
+
= render 'projects/activity'
diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml
index a1ae1397584..42f632b38ef 100644
--- a/app/views/projects/blob/_blob.html.haml
+++ b/app/views/projects/blob/_blob.html.haml
@@ -1,19 +1,22 @@
-%ul.breadcrumb.repo-breadcrumb
- %li
- %i.fa.fa-angle-right
- = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
- = @project.path
- - tree_breadcrumbs(@tree, 6) do |title, path|
+.gray-content-block.top-block
+ .tree-ref-holder
+ = render 'shared/ref_switcher', destination: 'blob', path: @path
+
+ %ul.breadcrumb.repo-breadcrumb
%li
- - if path
- - if path.end_with?(@path)
- = link_to namespace_project_blob_path(@project.namespace, @project, path) do
- %strong
- = truncate(title, length: 40)
+ = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
+ = @project.path
+ - tree_breadcrumbs(@tree, 6) do |title, path|
+ %li
+ - if path
+ - if path.end_with?(@path)
+ = link_to namespace_project_blob_path(@project.namespace, @project, path) do
+ %strong
+ = truncate(title, length: 40)
+ - else
+ = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
- else
- = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
- - else
- = link_to title, '#'
+ = link_to title, '#'
%ul.blob-commit-info.hidden-xs
- blob_commit = @repository.last_commit_for_path(@commit.id, blob.path)
diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml
index cb1567a2e68..a0fc8bbd752 100644
--- a/app/views/projects/blob/_new_dir.html.haml
+++ b/app/views/projects/blob/_new_dir.html.haml
@@ -21,5 +21,5 @@
= submit_tag "Create directory", class: 'btn btn-primary btn-create'
= link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
-:coffeescript
+:javascript
disableButtonIfAnyEmptyField($("#dir-create-form"), ".form-control", ".btn-create");
diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml
index e27f1707527..a1c54e731f0 100644
--- a/app/views/projects/blob/_upload.html.haml
+++ b/app/views/projects/blob/_upload.html.haml
@@ -26,6 +26,6 @@
= button_tag button_title, class: 'btn btn-small btn-primary btn-upload-file', id: 'submit-all'
= link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal"
-:coffeescript
- disableButtonIfEmptyField $('.blob-file-upload-form-js').find('#commit_message'), '.btn-upload-file'
- new BlobFileDropzone($('.blob-file-upload-form-js'), '#{method}')
+:javascript
+ disableButtonIfEmptyField($('.blob-file-upload-form-js').find('#commit_message'), '.btn-upload-file');
+ new BlobFileDropzone($('.blob-file-upload-form-js'), '#{method}');
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index fa4be4a1bc4..f52b89f6921 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -3,9 +3,6 @@
= render 'projects/last_push'
-%div.tree-ref-holder
- = render 'shared/ref_switcher', destination: 'blob', path: @path
-
%div#tree-holder.tree-holder
= render 'blob', blob: @blob
diff --git a/app/views/projects/branches/_commit.html.haml b/app/views/projects/branches/_commit.html.haml
index 68326e65d85..22d77dda938 100644
--- a/app/views/projects/branches/_commit.html.haml
+++ b/app/views/projects/branches/_commit.html.haml
@@ -1,5 +1,5 @@
-.branch-commit.light
- = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
+.branch-commit
+ = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-id"
&middot;
%span.str-truncated
= link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message"
diff --git a/app/views/projects/builds/_build.html.haml b/app/views/projects/builds/_build.html.haml
deleted file mode 100644
index 4ce4ed63b40..00000000000
--- a/app/views/projects/builds/_build.html.haml
+++ /dev/null
@@ -1,53 +0,0 @@
-%tr.build
- %td.status
- = ci_status_with_icon(build.status)
-
- %td.commit_status-link
- - if build.target_url
- = link_to build.target_url do
- %strong Build ##{build.id}
- - else
- %strong Build ##{build.id}
-
- - if build.show_warning?
- %i.fa.fa-warning.text-warning
-
- %td
- = link_to build.short_sha, namespace_project_commit_path(@project.namespace, @project, build.sha)
-
- %td
- = link_to build.ref, namespace_project_commits_path(@project.namespace, @project, build.ref)
-
- %td
- - if build.runner
- = runner_link(build.runner)
- - else
- .light none
-
- %td
- = build.name
-
- .pull-right
- - if build.tags.any?
- - build.tags.each do |tag|
- %span.label.label-primary
- = tag
- - if build.trigger_request
- %span.label.label-info triggered
- - if build.allow_failure
- %span.label.label-danger allowed to fail
-
- %td.duration
- - if build.duration
- #{duration_in_words(build.finished_at, build.started_at)}
-
- %td.timestamp
- - if build.finished_at
- %span #{time_ago_in_words build.finished_at} ago
-
- %td
- .pull-right
- - if current_user && can?(current_user, :manage_builds, @project)
- - if build.cancel_url
- = link_to build.cancel_url, title: 'Cancel' do
- %i.fa.fa-remove.cred
diff --git a/app/views/projects/builds/_header_title.html.haml b/app/views/projects/builds/_header_title.html.haml
new file mode 100644
index 00000000000..082dab1f5b0
--- /dev/null
+++ b/app/views/projects/builds/_header_title.html.haml
@@ -0,0 +1 @@
+- header_title project_title(@project, "Builds", project_builds_path(@project))
diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml
index 4d8ca16d98a..dab7164153f 100644
--- a/app/views/projects/builds/index.html.haml
+++ b/app/views/projects/builds/index.html.haml
@@ -1,12 +1,12 @@
- page_title "Builds"
-- header_title project_title(@project, "Builds", project_builds_path(@project))
+= render "header_title"
.project-issuable-filter
.controls
- if @ci_project && current_user && can?(current_user, :manage_builds, @project)
.pull-left.hidden-xs
- if @all_builds.running_or_pending.any?
- = link_to 'Cancel all', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger'
+ = link_to 'Cancel all', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post
%ul.center-top-menu
%li{class: ('active' if @scope.nil?)}
@@ -25,28 +25,29 @@
%span.badge.js-totalbuilds-count= @all_builds.count(:id)
.gray-content-block
- List of #{@scope || 'running'} builds from this project
+ #{(@scope || 'running').capitalize} builds from this project
%ul.content-list
- if @builds.blank?
%li
.nothing-here-block No builds to show
- else
- %table.table.builds
- %thead
- %tr
- %th Status
- %th Build ID
- %th Commit
- %th Ref
- %th Runner
- %th Name
- %th Duration
- %th Finished at
- %th
-
- - @builds.each do |build|
- = render 'projects/builds/build', build: build
-
- = paginate @builds
+ .table-holder
+ %table.table.builds
+ %thead
+ %tr
+ %th Status
+ %th Build ID
+ %th Commit
+ %th Ref
+ %th Stage
+ %th Name
+ %th Duration
+ %th Finished at
+ %th
+
+ - @builds.each do |build|
+ = render 'projects/commit_statuses/commit_status', commit_status: build, commit_sha: true, stage: true, allow_retry: true
+
+ = paginate @builds, theme: 'gitlab'
diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml
index c45bfb27b8f..907e1ce10bd 100644
--- a/app/views/projects/builds/show.html.haml
+++ b/app/views/projects/builds/show.html.haml
@@ -1,10 +1,13 @@
+- page_title "#{@build.name} (#{@build.id})", "Builds"
+= render "header_title"
+
.build-page
.gray-content-block
- Build for commit
+ Build ##{@build.id} for commit
%strong.monospace
= link_to @build.commit.short_sha, ci_status_path(@build.commit)
from
- %code #{@build.ref}
+ = link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
#up-build-trace
- if @commit.matrix_for_ref?(@build.ref)
@@ -20,7 +23,7 @@
= build.id
- - unless @commit.latest_builds_for_ref(@build.ref).include?(@build)
+ - if @build.retried?
%li.active
%a
Build ##{@build.id}
@@ -37,7 +40,7 @@
%i.fa.fa-time
#{duration_in_words(@build.finished_at, @build.started_at)}
.pull-right
- = @build.updated_at.stamp('19:00 Aug 27')
+ #{time_ago_with_tooltip(@build.finished_at) if @build.finished_at}
- if @build.show_warning?
- unless @build.any_runners_online?
@@ -84,16 +87,19 @@
Test coverage
%h1 #{@build.coverage}%
+ - if current_user && can?(current_user, :download_build_artifacts, @project) && @build.download_url
+ .build-widget.center
+ = link_to "Download artifacts", @build.download_url, class: 'btn btn-sm btn-primary'
.build-widget
%h4.title
- Build
+ Build ##{@build.id}
- if current_user && can?(current_user, :manage_builds, @project)
.pull-right
- - if @build.active?
- = link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-danger'
- - elsif @build.commands.present?
- = link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-primary', method: :post
+ - if @build.cancel_url
+ = link_to "Cancel", @build.cancel_url, class: 'btn btn-sm btn-danger', method: :post
+ - elsif @build.retry_url
+ = link_to "Retry", @build.retry_url, class: 'btn btn-sm btn-primary', method: :post
- if @build.duration
%p
@@ -101,15 +107,15 @@
#{duration_in_words(@build.finished_at, @build.started_at)}
%p
%span.attr-name Created:
- #{time_ago_in_words(@build.created_at)} ago
+ #{time_ago_with_tooltip(@build.created_at)}
- if @build.finished_at
%p
%span.attr-name Finished:
- #{time_ago_in_words(@build.finished_at)} ago
+ #{time_ago_with_tooltip(@build.finished_at)}
%p
%span.attr-name Runner:
- if @build.runner && current_user && current_user.admin
- \#{link_to "##{@build.runner.id}", ci_admin_runner_path(@build.runner.id)}
+ = link_to "##{@build.runner.id}", ci_admin_runner_path(@build.runner.id)
- elsif @build.runner
\##{@build.runner.id}
@@ -134,10 +140,11 @@
%h4.title
Commit
.pull-right
- %small #{build_commit_link @build}
+ %small
+ = link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace"
%p
%span.attr-name Branch:
- #{build_ref_link @build}
+ = link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
%p
%span.attr-name Author:
#{@build.commit.git_author_name}
@@ -155,14 +162,16 @@
- if @builds.present?
.build-widget
- %h4.title #{pluralize(@builds.count, "other build")} for #{@build.short_sha}:
+ %h4.title #{pluralize(@builds.count(:id), "other build")} for
+ = succeed ":" do
+ = link_to @build.commit.short_sha, ci_status_path(@build.commit), class: "monospace"
%table.table.builds
- @builds.each_with_index do |build, i|
%tr.build
%td
= ci_icon_for_status(build.status)
%td
- = link_to namespace_project_build_path(@project.namespace, @project, @build) do
+ = link_to namespace_project_build_path(@project.namespace, @project, build) do
- if build.name
= build.name
- else
@@ -171,8 +180,5 @@
%td.status= build.status
- = paginate @builds
-
-
:javascript
- new CiBuild("#{namespace_project_build_path(@project.namespace, @project, @build)}", "#{@build.status}")
+ new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}")
diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml
index 4580c912692..18cae8ef6d3 100644
--- a/app/views/projects/buttons/_dropdown.html.haml
+++ b/app/views/projects/buttons/_dropdown.html.haml
@@ -5,7 +5,7 @@
%ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
- if can?(current_user, :create_issue, @project)
%li
- = link_to url_for_new_issue do
+ = link_to url_for_new_issue(@project, only_path: true) do
= icon('exclamation-circle fw')
New issue
- if can?(current_user, :create_merge_request, @project)
@@ -21,6 +21,10 @@
- if can?(current_user, :push_code, @project)
%li.divider
%li
+ = link_to namespace_project_new_blob_path(@project.namespace, @project, @project.default_branch || 'master'), title: 'New file' do
+ = icon('file fw')
+ New file
+ %li
= link_to new_namespace_project_branch_path(@project.namespace, @project) do
= icon('code-fork fw')
New branch
diff --git a/app/views/projects/buttons/_notifications.html.haml b/app/views/projects/buttons/_notifications.html.haml
index 3bc2daeec4e..3e83ec3912f 100644
--- a/app/views/projects/buttons/_notifications.html.haml
+++ b/app/views/projects/buttons/_notifications.html.haml
@@ -1,14 +1,20 @@
-- return unless @membership
+- case @membership
+- when ProjectMember
+ = form_tag profile_notifications_path, method: :put, remote: true, class: 'inline', id: 'notification-form' do
+ = hidden_field_tag :notification_type, 'project'
+ = hidden_field_tag :notification_id, @membership.id
+ = hidden_field_tag :notification_level
+ %span.dropdown
+ %a.dropdown-new.btn.notifications-btn#notifications-button{href: '#', "data-toggle" => "dropdown"}
+ = icon('bell')
+ = notification_label(@membership)
+ = icon('angle-down')
+ %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
+ - Notification.project_notification_levels.each do |level|
+ = notification_list_item(level, @membership)
-= form_tag profile_notifications_path, method: :put, remote: true, class: 'inline', id: 'notification-form' do
- = hidden_field_tag :notification_type, 'project'
- = hidden_field_tag :notification_id, @membership.id
- = hidden_field_tag :notification_level
- %span.dropdown
- %a.dropdown-new.btn.btn-new#notifications-button{href: '#', "data-toggle" => "dropdown"}
- = icon('bell')
- = notification_label(@membership)
- = icon('angle-down')
- %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
- - Notification.project_notification_levels.each do |level|
- = notification_list_item(level, @membership)
+- when GroupMember
+ .btn.disabled.notifications-btn.has_tooltip{title: "To change the notification level, you need to be a member of the project itself, not only its group."}
+ = icon('bell')
+ = notification_label(@membership)
+ = icon('angle-down')
diff --git a/app/views/projects/buttons/_star.html.haml b/app/views/projects/buttons/_star.html.haml
index 3501dddefbe..06583902035 100644
--- a/app/views/projects/buttons/_star.html.haml
+++ b/app/views/projects/buttons/_star.html.haml
@@ -4,11 +4,13 @@
%span.count
= @project.star_count
- :coffeescript
- $('.project-home-panel .toggle-star').on 'ajax:success', (e, data, status, xhr) ->
- $(@).replaceWith(data.html)
- .on 'ajax:error', (e, xhr, status, error) ->
- new Flash('Star toggle failed. Try again later.', 'alert')
+ :javascript
+ $('.project-home-panel .toggle-star').on('ajax:success', function (e, data, status, xhr) {
+ $(this).replaceWith(data.html);
+ })
+ .on('ajax:error', function (e, xhr, status, error) {
+ new Flash('Star toggle failed. Try again later.', 'alert');
+ });
- else
= link_to new_user_session_path, class: 'btn has_tooltip star-btn', title: 'You must sign in to star a project' do
diff --git a/app/views/projects/ci_services/edit.html.haml b/app/views/projects/ci_services/edit.html.haml
index bcc5832792f..dacb6b4f6f4 100644
--- a/app/views/projects/ci_services/edit.html.haml
+++ b/app/views/projects/ci_services/edit.html.haml
@@ -1 +1,2 @@
+- page_title @service.title, "CI Services"
= render 'form'
diff --git a/app/views/projects/ci_services/index.html.haml b/app/views/projects/ci_services/index.html.haml
index c78b21884a3..3f26c7851d8 100644
--- a/app/views/projects/ci_services/index.html.haml
+++ b/app/views/projects/ci_services/index.html.haml
@@ -1,3 +1,4 @@
+- page_title "CI Services"
%h3.page-title Project services
%p.light Project services allow you to integrate GitLab CI with other applications
@@ -6,7 +7,7 @@
%tr
%th
%th Service
- %th Desription
+ %th Description
%th Last edit
- @services.sort_by(&:title).each do |service|
%tr
diff --git a/app/views/projects/ci_settings/_form.html.haml b/app/views/projects/ci_settings/_form.html.haml
index d711413c6b9..ee6b8885e2d 100644
--- a/app/views/projects/ci_settings/_form.html.haml
+++ b/app/views/projects/ci_settings/_form.html.haml
@@ -102,9 +102,10 @@
%code \(\d+.\d+\%\) covered
%li
pytest-cov (Python) -
- %code \d+\%$
-
-
+ %code \d+\%\s*$
+ %li
+ phpunit --coverage-text --colors=never (PHP) -
+ %code ^\s*Lines:\s*\d+.\d+\%
%fieldset
%legend Advanced settings
diff --git a/app/views/projects/ci_settings/_no_runners.html.haml b/app/views/projects/ci_settings/_no_runners.html.haml
index 33038c52978..1374e6680f9 100644
--- a/app/views/projects/ci_settings/_no_runners.html.haml
+++ b/app/views/projects/ci_settings/_no_runners.html.haml
@@ -5,4 +5,4 @@
You can add Specific runner for this project on Runners page
- if current_user.admin
- or add Shared runner for whole application in admin are.
+ or add Shared runner for whole application in admin area.
diff --git a/app/views/projects/ci_settings/edit.html.haml b/app/views/projects/ci_settings/edit.html.haml
index eedf484bf00..acc912d4596 100644
--- a/app/views/projects/ci_settings/edit.html.haml
+++ b/app/views/projects/ci_settings/edit.html.haml
@@ -1,24 +1,6 @@
-- if @ci_project.generated_yaml_config
- %p.alert.alert-danger
- CI Jobs are deprecated now, you can #{link_to "download", dumped_yaml_ci_project_path(@ci_project)}
- or
- %a.preview-yml{:href => "#yaml-content", "data-toggle" => "modal"} preview
- yaml file which is based on your old jobs.
- Put this file to the root of your project and name it .gitlab-ci.yml
+- page_title "CI Settings"
- if no_runners_for_project?(@ci_project)
= render 'no_runners'
= render 'form'
-
-- if @ci_project.generated_yaml_config
- #yaml-content.modal.fade{"aria-hidden" => "true", "aria-labelledby" => ".gitlab-ci.yml", :role => "dialog", :tabindex => "-1"}
- .modal-dialog
- .modal-content
- .modal-header
- %button.close{"aria-hidden" => "true", "data-dismiss" => "modal", :type => "button"} ×
- %h4.modal-title Content of .gitlab-ci.yml
- .modal-body
- = text_area_tag :yaml, @ci_project.generated_yaml_config, size: "70x25", class: "form-control"
- .modal-footer
- %button.btn.btn-default{"data-dismiss" => "modal", :type => "button"} Close
diff --git a/app/views/projects/ci_web_hooks/index.html.haml b/app/views/projects/ci_web_hooks/index.html.haml
index 6aebd7cfc4d..2998fb08ff1 100644
--- a/app/views/projects/ci_web_hooks/index.html.haml
+++ b/app/views/projects/ci_web_hooks/index.html.haml
@@ -1,3 +1,4 @@
+- page_title "CI Web Hooks"
%h3.page-title
CI Web hooks
@@ -20,17 +21,18 @@
-if @web_hooks.any?
%h4 Activated web hooks (#{@web_hooks.count})
- %table.table
- - @web_hooks.each do |hook|
- %tr
- %td
- .clearfix
- %span.monospace= hook.url
- %td
- .pull-right
- - if @ci_project.commits.any?
- = link_to 'Test Hook', test_namespace_project_ci_web_hook_path(@project.namespace, @project, hook), class: "btn btn-sm btn-grouped"
- = link_to 'Remove', namespace_project_ci_web_hook_path(@project.namespace, @project, hook), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove btn-sm btn-grouped"
+ .table-holder
+ %table.table
+ - @web_hooks.each do |hook|
+ %tr
+ %td
+ .clearfix
+ %span.monospace= hook.url
+ %td
+ .pull-right
+ - if @ci_project.commits.any?
+ = link_to 'Test Hook', test_namespace_project_ci_web_hook_path(@project.namespace, @project, hook), class: "btn btn-sm btn-grouped"
+ = link_to 'Remove', namespace_project_ci_web_hook_path(@project.namespace, @project, hook), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove btn-sm btn-grouped"
%h4 Web Hook data example
diff --git a/app/views/projects/commit/_ci_menu.html.haml b/app/views/projects/commit/_ci_menu.html.haml
index a634ae5dfda..c73ba74f5ef 100644
--- a/app/views/projects/commit/_ci_menu.html.haml
+++ b/app/views/projects/commit/_ci_menu.html.haml
@@ -2,6 +2,8 @@
= nav_link(path: 'commit#show') do
= link_to namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Changes
- = nav_link(path: 'commit#ci') do
- = link_to ci_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
+ %span.badge= @diffs.count
+ = nav_link(path: 'commit#builds') do
+ = link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Builds
+ %span.badge= @builds.count(:id)
diff --git a/app/views/projects/commit/_commit_box.html.haml b/app/views/projects/commit/_commit_box.html.haml
index fbf0a9ec0c3..776768537d0 100644
--- a/app/views/projects/commit/_commit_box.html.haml
+++ b/app/views/projects/commit/_commit_box.html.haml
@@ -19,7 +19,7 @@
%p
%span.light Commit
- = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit)
+ = link_to @commit.id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace"
.commit-info-row
%span.light Authored by
%strong
@@ -36,7 +36,7 @@
.commit-info-row
%span.cgray= pluralize(@commit.parents.count, "parent")
- @commit.parents.each do |parent|
- = link_to parent.short_id, namespace_project_commit_path(@project.namespace, @project, parent)
+ = link_to parent.short_id, namespace_project_commit_path(@project.namespace, @project, parent), class: "monospace"
- if @ci_commit
.pull-right
@@ -55,5 +55,5 @@
%pre.commit-description
= preserve(gfm(escape_once(@commit.description)))
-:coffeescript
- $(".commit-info-row.branches").load("#{branches_namespace_project_commit_path(@project.namespace, @project, @commit.id)}")
+:javascript
+ $(".commit-info-row.branches").load("#{branches_namespace_project_commit_path(@project.namespace, @project, @commit.id)}");
diff --git a/app/views/projects/commit/builds.html.haml b/app/views/projects/commit/builds.html.haml
new file mode 100644
index 00000000000..00cf9c76102
--- /dev/null
+++ b/app/views/projects/commit/builds.html.haml
@@ -0,0 +1,72 @@
+- page_title "Builds", "#{@commit.title} (#{@commit.short_id})", "Commits"
+= render "projects/commits/header_title"
+= render "commit_box"
+= render "ci_menu"
+
+
+- if @ci_commit.yaml_errors.present?
+ .bs-callout.bs-callout-danger
+ %h4 Found errors in your .gitlab-ci.yml:
+ %ul
+ - @ci_commit.yaml_errors.split(",").each do |error|
+ %li= error
+
+- unless @ci_commit.ci_yaml_file
+ .bs-callout.bs-callout-warning
+ \.gitlab-ci.yml not found in this commit
+
+.gray-content-block.second-block
+ Latest builds
+
+ .pull-right
+ - if @ci_commit.duration > 0
+ %i.fa.fa-time
+ #{time_interval_in_words @ci_commit.duration}
+
+ &nbsp;
+
+ - if @ci_project && current_user && can?(current_user, :manage_builds, @project)
+ - if @ci_commit.builds.latest.failed.any?(&:retryable?)
+ = link_to "Retry failed", retry_builds_namespace_project_commit_path(@project.namespace, @project, @commit.sha), class: 'btn btn-xs btn-primary', method: :post
+
+ - if @ci_commit.builds.running_or_pending.any?
+ = link_to "Cancel running", cancel_builds_namespace_project_commit_path(@project.namespace, @project, @commit.sha), class: 'btn btn-xs btn-danger', method: :post
+
+.table-holder
+ %table.table.builds
+ %thead
+ %tr
+ %th Status
+ %th Build ID
+ %th Ref
+ %th Stage
+ %th Name
+ %th Duration
+ %th Finished at
+ - if @ci_project && @ci_project.coverage_enabled?
+ %th Coverage
+ %th
+ - @ci_commit.refs.each do |ref|
+ = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest.ordered,
+ locals: { coverage: @ci_project.try(:coverage_enabled?), stage: true, allow_retry: true }
+
+- if @ci_commit.retried.any?
+ .gray-content-block.second-block
+ Retried builds
+
+ .table-holder
+ %table.table.builds
+ %thead
+ %tr
+ %th Status
+ %th Build ID
+ %th Ref
+ %th Stage
+ %th Name
+ %th Duration
+ %th Finished at
+ - if @ci_project && @ci_project.coverage_enabled?
+ %th Coverage
+ %th
+ = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried,
+ locals: { coverage: @ci_project.try(:coverage_enabled?), stage: true }
diff --git a/app/views/projects/commit/ci.html.haml b/app/views/projects/commit/ci.html.haml
deleted file mode 100644
index ca71a91af15..00000000000
--- a/app/views/projects/commit/ci.html.haml
+++ /dev/null
@@ -1,67 +0,0 @@
-- page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
-= render "projects/commits/header_title"
-= render "commit_box"
-= render "ci_menu"
-
-
-- if @ci_commit.yaml_errors.present?
- .bs-callout.bs-callout-danger
- %h4 Found errors in your .gitlab-ci.yml:
- %ul
- - @ci_commit.yaml_errors.split(",").each do |error|
- %li= error
-
-- unless @ci_commit.ci_yaml_file
- .bs-callout.bs-callout-warning
- \.gitlab-ci.yml not found in this commit
-
-.gray-content-block.second-block
- Latest builds
-
- .pull-right
- - if @ci_commit.duration > 0
- %i.fa.fa-time
- #{time_interval_in_words @ci_commit.duration}
-
- &nbsp;
-
- - if @ci_project && current_user && can?(current_user, :manage_builds, @project)
- - if @ci_commit.builds.running_or_pending.any?
- = link_to "Cancel all", cancel_builds_namespace_project_commit_path(@project.namespace, @project, @commit.sha), class: 'btn btn-xs btn-danger'
-
-%table.table.builds
- %thead
- %tr
- %th Status
- %th Build ID
- %th Ref
- %th Stage
- %th Name
- %th Duration
- %th Finished at
- - if @ci_project && @ci_project.coverage_enabled?
- %th Coverage
- %th
- - @ci_commit.refs.each do |ref|
- = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.statuses.for_ref(ref).latest.ordered,
- locals: { coverage: @ci_project.try(:coverage_enabled?), allow_retry: true }
-
-- if @ci_commit.retried.any?
- .gray-content-block.second-block
- Retried builds
-
- %table.table.builds
- %thead
- %tr
- %th Status
- %th Build ID
- %th Ref
- %th Stage
- %th Name
- %th Duration
- %th Finished at
- - if @ci_project && @ci_project.coverage_enabled?
- %th Coverage
- %th
- = render partial: "projects/commit_statuses/commit_status", collection: @ci_commit.retried,
- locals: { coverage: @ci_project.try(:coverage_enabled?) }
diff --git a/app/views/projects/commit_statuses/_commit_status.html.haml b/app/views/projects/commit_statuses/_commit_status.html.haml
index 637154f56aa..9a0e7bff3f1 100644
--- a/app/views/projects/commit_statuses/_commit_status.html.haml
+++ b/app/views/projects/commit_statuses/_commit_status.html.haml
@@ -12,14 +12,30 @@
- if commit_status.show_warning?
%i.fa.fa-warning.text-warning
- %td
- = commit_status.ref
+ - if defined?(commit_sha) && commit_sha
+ %td
+ = link_to commit_status.short_sha, namespace_project_commit_path(@project.namespace, @project, commit_status.sha), class: "monospace"
%td
- = commit_status.stage
+ - if commit_status.ref
+ = link_to commit_status.ref, namespace_project_commits_path(@project.namespace, @project, commit_status.ref)
+ - else
+ .light none
+
+ - if defined?(runner) && runner
+ %td
+ - if commit_status.try(:runner)
+ = runner_link(commit_status.runner)
+ - else
+ .light none
+
+ - if defined?(stage) && stage
+ %td
+ = commit_status.stage
%td
= commit_status.name
+
.pull-right
- if commit_status.tags.any?
- commit_status.tags.each do |tag|
@@ -36,7 +52,7 @@
%td.timestamp
- if commit_status.finished_at
- %span #{time_ago_in_words commit_status.finished_at} ago
+ %span #{time_ago_with_tooltip(commit_status.finished_at)}
- if defined?(coverage) && coverage
%td.coverage
@@ -45,10 +61,14 @@
%td
.pull-right
+ - if current_user && can?(current_user, :download_build_artifacts, @project) && commit_status.download_url
+ = link_to commit_status.download_url, title: 'Download artifacts' do
+ %i.fa.fa-download
- if current_user && can?(current_user, :manage_builds, commit_status.gl_project)
- - if commit_status.cancel_url
- = link_to commit_status.cancel_url, title: 'Cancel' do
- %i.fa.fa-remove.cred
+ - if commit_status.active?
+ - if commit_status.cancel_url
+ = link_to commit_status.cancel_url, method: :post, title: 'Cancel' do
+ %i.fa.fa-remove.cred
- elsif defined?(allow_retry) && allow_retry && commit_status.retry_url
= link_to commit_status.retry_url, method: :post, title: 'Retry' do
%i.fa.fa-repeat
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index cddd5aa3a83..805be332e64 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -18,10 +18,10 @@
.pull-right
- if ci_commit
- = link_to ci_status_path(ci_commit), class: "c#{ci_status_color(ci_commit)}" do
- = ci_status_icon(ci_commit)
+ = render_ci_status(ci_commit)
&nbsp;
- = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
+ = clipboard_button
+ = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id", data: {clipboard_text: commit.id}
.notes_count
- if note_count > 0
diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml
index a849bf84698..f11a41cfd7b 100644
--- a/app/views/projects/commits/_head.html.haml
+++ b/app/views/projects/commits/_head.html.haml
@@ -12,7 +12,7 @@
Branches
%span.badge.js-totalbranch-count= @repository.branches.size
- = nav_link(controller: :tags) do
+ = nav_link(controller: [:tags, :releases]) do
= link_to namespace_project_tags_path(@project.namespace, @project) do
Tags
%span.badge.js-totaltags-count= @repository.tags.length
diff --git a/app/views/projects/commits/show.atom.builder b/app/views/projects/commits/show.atom.builder
index 3854ad5d611..268b9b815ee 100644
--- a/app/views/projects/commits/show.atom.builder
+++ b/app/views/projects/commits/show.atom.builder
@@ -12,7 +12,7 @@ xml.feed "xmlns" => "http://www.w3.org/2005/Atom", "xmlns:media" => "http://sear
xml.link href: namespace_project_commit_url(@project.namespace, @project, id: commit.id)
xml.title truncate(commit.title, length: 80)
xml.updated commit.committed_date.strftime("%Y-%m-%dT%H:%M:%SZ")
- xml.media :thumbnail, width: "40", height: "40", url: avatar_icon(commit.author_email)
+ xml.media :thumbnail, width: "40", height: "40", url: image_url(avatar_icon(commit.author_email))
xml.author do |author|
xml.name commit.author_name
xml.email commit.author_email
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 4f1965bfb39..e46bf1ab1e7 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -3,7 +3,7 @@
- diff_files = safe_diff_files(diffs)
-.gray-content-block.second-block
+.gray-content-block.second-block.oneline-block
.inline-parallel-buttons
.btn-group
= inline_diff_btn
@@ -15,8 +15,8 @@
.files
- diff_files.each_with_index do |diff_file, index|
- - diff_commit = commit_for_diff(diff_file.diff)
- - blob = project.repository.blob_for_diff(diff_commit, diff_file.diff)
+ - diff_commit = commit_for_diff(diff_file)
+ - blob = project.repository.blob_for_diff(diff_commit, diff_file)
- next unless blob
= render 'projects/diffs/file', i: index, project: project,
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index 9698921f6da..410ff6abb43 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -1,5 +1,5 @@
.diff-file{id: "diff-#{i}", data: diff_file_html_data(project, diff_commit, diff_file)}
- .diff-header{id: "file-path-#{hexdigest(diff_file.new_path || diff_file.old_path)}"}
+ .diff-header{id: "file-path-#{hexdigest(diff_file.file_path)}"}
- if diff_file.diff.submodule?
%span
- submodule_item = project.repository.blob_at(@commit.id, diff_file.file_path)
@@ -38,7 +38,7 @@
- else
= render "projects/diffs/text_file", diff_file: diff_file, index: i
- elsif blob.image?
- - old_file = project.repository.prev_blob_for_diff(@commit, diff_file)
+ - old_file = project.repository.prev_blob_for_diff(diff_commit, diff_file)
= render "projects/diffs/image", diff_file: diff_file, old_file: old_file, file: blob, index: i
- else
.nothing-here-block No preview for this file type
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 1882a82fba5..3ebc175648e 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -57,7 +57,16 @@
= f.check_box :merge_requests_enabled
%strong Merge Requests
%br
- %span.descr Submit changes to be merged upstream.
+ %span.descr Submit changes to be merged upstream
+
+ .form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :builds_enabled do
+ = f.check_box :builds_enabled
+ %strong Builds
+ %br
+ %span.descr Test and deploy your changes before merge
.form-group
.col-sm-offset-2.col-sm-10
@@ -189,6 +198,21 @@
- else
.nothing-here-block Only the project owner can transfer a project
+ - if @project.forked?
+ - if can?(current_user, :remove_fork_project, @project)
+ = form_for([@project.namespace.becomes(Namespace), @project], url: remove_fork_namespace_project_path(@project.namespace, @project), method: :delete, remote: true, html: { class: 'transfer-project form-horizontal' }) do |f|
+ .panel.panel-default.panel.panel-danger
+ .panel-heading Remove fork relationship
+ .panel-body
+ %p
+ This will remove the fork relationship to source project
+ #{link_to @project.forked_from_project.name_with_namespace, project_path(@project.forked_from_project)}.
+ %br
+ %strong Once removed, the fork relationship cannot be restored and you will no longer be able to send merge requests to the source.
+ = button_to 'Remove fork relationship', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_message(@project) }
+ - else
+ .nothing-here-block Only the project owner can remove the fork relationship.
+
- if can?(current_user, :remove_project, @project)
.panel.panel-default.panel.panel-danger
.panel-heading Remove project
@@ -201,7 +225,8 @@
= button_to 'Remove project', '#', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => remove_project_message(@project) }
- else
- .nothing-here-block Only project owner can remove a project
+ .nothing-here-block Only the project owner can remove a project.
+
.save-project-loader.hide
.center
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index e06454fd148..c3858e78cad 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -2,53 +2,56 @@
- if current_user && can?(current_user, :download_code, @project)
= render 'shared/no_ssh'
= render 'shared/no_password'
-
+
= render "home_panel"
.gray-content-block.center
%h3.page-title
The repository for this project is empty
- %p
- If you already have files you can push them using command line instructions below.
- %br
- Otherwise you can start with
- = link_to "adding README", new_readme_path, class: 'underlined-link'
- file to this project.
+ - if can?(current_user, :download_code, @project)
+ %p
+ If you already have files you can push them using command line instructions below.
+ %br
+ - if can?(current_user, :push_code, @project)
+ Otherwise you can start with
+ = link_to "adding README", new_readme_path, class: 'underlined-link'
+ file to this project.
-.prepend-top-20
-.empty_wrapper
- %h3.page-title-empty
- Command line instructions
- %div.git-empty
- %fieldset
- %h5 Git global setup
- %pre.light-well
- :preserve
- git config --global user.name "#{h git_user_name}"
- git config --global user.email "#{h git_user_email}"
+- if can?(current_user, :download_code, @project)
+ .prepend-top-20
+ .empty_wrapper
+ %h3.page-title-empty
+ Command line instructions
+ %div.git-empty
+ %fieldset
+ %h5 Git global setup
+ %pre.light-well
+ :preserve
+ git config --global user.name "#{h git_user_name}"
+ git config --global user.email "#{h git_user_email}"
- %fieldset
- %h5 Create a new repository
- %pre.light-well
- :preserve
- git clone #{ content_tag(:span, default_url_to_repo, class: 'clone')}
- cd #{h @project.path}
- touch README.md
- git add README.md
- git commit -m "add README"
- git push -u origin master
+ %fieldset
+ %h5 Create a new repository
+ %pre.light-well
+ :preserve
+ git clone #{ content_tag(:span, default_url_to_repo, class: 'clone')}
+ cd #{h @project.path}
+ touch README.md
+ git add README.md
+ git commit -m "add README"
+ git push -u origin master
- %fieldset
- %h5 Existing folder or Git repository
- %pre.light-well
- :preserve
- cd existing_folder
- git init
- git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
- git add .
- git commit
- git push -u origin master
+ %fieldset
+ %h5 Existing folder or Git repository
+ %pre.light-well
+ :preserve
+ cd existing_folder
+ git init
+ git remote add origin #{ content_tag(:span, default_url_to_repo, class: 'clone')}
+ git add .
+ git commit
+ git push -u origin master
- - if can? current_user, :remove_project, @project
- .prepend-top-20
- = link_to 'Remove project', [@project.namespace.becomes(Namespace), @project], data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
+ - if can? current_user, :remove_project, @project
+ .prepend-top-20
+ = link_to 'Remove project', [@project.namespace.becomes(Namespace), @project], data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-remove pull-right"
diff --git a/app/views/projects/graphs/_head.html.haml b/app/views/projects/graphs/_head.html.haml
index bbfaf422a82..03d0733f913 100644
--- a/app/views/projects/graphs/_head.html.haml
+++ b/app/views/projects/graphs/_head.html.haml
@@ -1,9 +1,9 @@
-%ul.nav.nav-tabs
+%ul.center-top-menu
= nav_link(action: :show) do
= link_to 'Contributors', namespace_project_graph_path
= nav_link(action: :commits) do
= link_to 'Commits', commits_namespace_project_graph_path
- - if @project.gitlab_ci?
+ - if @project.builds_enabled?
= nav_link(action: :ci) do
= link_to ci_namespace_project_graph_path do
Continuous Integration
diff --git a/app/views/projects/graphs/ci.html.haml b/app/views/projects/graphs/ci.html.haml
index 4f69cc64f7c..6fa77cc10c6 100644
--- a/app/views/projects/graphs/ci.html.haml
+++ b/app/views/projects/graphs/ci.html.haml
@@ -1,7 +1,16 @@
- page_title "Continuous Integration", "Graphs"
= render "header_title"
= render 'head'
+.gray-content-block.append-bottom-default
+ .oneline
+ A collection of graphs for Continuous Integration
+
#charts.ci-charts
+ .row
+ .col-md-6
+ = render 'projects/graphs/ci/overall'
+ .col-md-6
+ = render 'projects/graphs/ci/build_times'
+
+ %hr
= render 'projects/graphs/ci/builds'
- = render 'projects/graphs/ci/build_times'
-= render 'projects/graphs/ci/overall'
diff --git a/app/views/projects/graphs/ci/_build_times.haml b/app/views/projects/graphs/ci/_build_times.haml
index c3c2f572414..c58223fd39e 100644
--- a/app/views/projects/graphs/ci/_build_times.haml
+++ b/app/views/projects/graphs/ci/_build_times.haml
@@ -1,21 +1,22 @@
-%fieldset
- %legend
+%div
+ %p.light
Commit duration in minutes for last 30 commits
- %canvas#build_timesChart.padded{width: 800, height: 300}
+ %canvas#build_timesChart{height: 200}
:javascript
var data = {
labels : #{@charts[:build_times].labels.to_json},
datasets : [
{
- fillColor : "#4A3",
- strokeColor : "rgba(151,187,205,1)",
- pointColor : "rgba(151,187,205,1)",
- pointStrokeColor : "#fff",
+ fillColor : "rgba(220,220,220,0.5)",
+ strokeColor : "rgba(220,220,220,1)",
+ barStrokeWidth: 1,
+ barValueSpacing: 1,
+ barDatasetSpacing: 1,
data : #{@charts[:build_times].build_times.to_json}
}
]
}
var ctx = $("#build_timesChart").get(0).getContext("2d");
- new Chart(ctx).Line(data,{"scaleOverlay": true});
+ new Chart(ctx).Bar(data,{"scaleOverlay": true, responsive: true, maintainAspectRatio: false});
diff --git a/app/views/projects/graphs/ci/_builds.haml b/app/views/projects/graphs/ci/_builds.haml
index 1b0039fb834..8fca07114fa 100644
--- a/app/views/projects/graphs/ci/_builds.haml
+++ b/app/views/projects/graphs/ci/_builds.haml
@@ -1,20 +1,30 @@
-%fieldset
- %legend
- Builds chart for last week
- (#{date_from_to(Date.today - 7.days, Date.today)})
+%h4 Build charts
+%p
+ &nbsp;
+ %span.cgreen
+ = icon("circle")
+ success
+ &nbsp;
+ %span.cgray
+ = icon("circle")
+ all
- %canvas#weekChart.padded{width: 800, height: 200}
+.prepend-top-default
+ %p.light
+ Builds for last week
+ (#{date_from_to(Date.today - 7.days, Date.today)})
+ %canvas#weekChart{height: 200}
-%fieldset
- %legend
- Builds chart for last month
+.prepend-top-default
+ %p.light
+ Builds for last month
(#{date_from_to(Date.today - 30.days, Date.today)})
+ %canvas#monthChart{height: 200}
- %canvas#monthChart.padded{width: 800, height: 300}
-
-%fieldset
- %legend Builds chart for last year
- %canvas#yearChart.padded{width: 800, height: 400}
+.prepend-top-default
+ %p.light
+ Builds for last year
+ %canvas#yearChart.padded{height: 250}
- [:week, :month, :year].each do |scope|
:javascript
@@ -22,20 +32,20 @@
labels : #{@charts[scope].labels.to_json},
datasets : [
{
- fillColor : "rgba(220,220,220,0.5)",
- strokeColor : "rgba(220,220,220,1)",
- pointColor : "rgba(220,220,220,1)",
+ fillColor : "#7f8fa4",
+ strokeColor : "#7f8fa4",
+ pointColor : "#7f8fa4",
pointStrokeColor : "#EEE",
data : #{@charts[scope].total.to_json}
},
{
- fillColor : "#4A3",
- strokeColor : "rgba(151,187,205,1)",
- pointColor : "rgba(151,187,205,1)",
+ fillColor : "#44aa22",
+ strokeColor : "#44aa22",
+ pointColor : "#44aa22",
pointStrokeColor : "#fff",
data : #{@charts[scope].success.to_json}
}
]
}
var ctx = $("##{scope}Chart").get(0).getContext("2d");
- new Chart(ctx).Line(data,{"scaleOverlay": true});
+ new Chart(ctx).Line(data,{"scaleOverlay": true, responsive: true, maintainAspectRatio: false});
diff --git a/app/views/projects/graphs/ci/_overall.haml b/app/views/projects/graphs/ci/_overall.haml
index 9550d719471..cf4285a2671 100644
--- a/app/views/projects/graphs/ci/_overall.haml
+++ b/app/views/projects/graphs/ci/_overall.haml
@@ -1,22 +1,20 @@
- ci_project = @project.gitlab_ci_project
-%fieldset
- %legend Overall
- %p
+%h4 Overall stats
+%ul
+ %li
Total:
%strong= pluralize ci_project.builds.count(:all), 'build'
- %p
+ %li
Successful:
%strong= pluralize ci_project.builds.success.count(:all), 'build'
- %p
+ %li
Failed:
%strong= pluralize ci_project.builds.failed.count(:all), 'build'
-
- %p
+ %li
Success ratio:
%strong
#{success_ratio(ci_project.builds.success, ci_project.builds.failed)}%
-
- %p
+ %li
Commits covered:
%strong
= ci_project.commits.count(:all)
diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml
index 112be875b6b..fc465ab273b 100644
--- a/app/views/projects/graphs/commits.html.haml
+++ b/app/views/projects/graphs/commits.html.haml
@@ -1,9 +1,13 @@
- page_title "Commits", "Graphs"
= render "header_title"
-.tree-ref-holder
- = render 'shared/ref_switcher', destination: 'graphs_commits'
= render 'head'
+.gray-content-block.append-bottom-default
+ .tree-ref-holder
+ = render 'shared/ref_switcher', destination: 'graphs_commits'
+ %ul.breadcrumb.repo-breadcrumb
+ = commits_breadcrumbs
+
%p.lead
Commit statistics for
%strong #{@ref}
@@ -45,26 +49,24 @@
Commits per weekday
%canvas#weekday-chart
-:coffeescript
- responsiveChart = (selector, data) ->
- options = { "scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2, maintainAspectRatio: false }
-
- # get selector by context
- ctx = selector.get(0).getContext("2d")
- # pointing parent container to make chart.js inherit its width
- container = $(selector).parent()
-
- generateChart = ->
- selector.attr('width', $(container).width())
- new Chart(ctx).Bar(data, options)
-
- # enabling auto-resizing
- $(window).resize( generateChart )
-
- generateChart()
+:javascript
+ var responsiveChart = function (selector, data) {
+ var options = { "scaleOverlay": true, responsive: true, pointHitDetectionRadius: 2, maintainAspectRatio: false };
+ // get selector by context
+ var ctx = selector.get(0).getContext("2d");
+ // pointing parent container to make chart.js inherit its width
+ var container = $(selector).parent();
+ var generateChart = function() {
+ selector.attr('width', $(container).width());
+ return new Chart(ctx).Bar(data, options);
+ };
+ // enabling auto-resizing
+ $(window).resize(generateChart);
+ return generateChart();
+ };
- chartData = (keys, values) ->
- data = {
+ var chartData = function (keys, values) {
+ var data = {
labels : keys,
datasets : [{
fillColor : "rgba(220,220,220,0.5)",
@@ -74,13 +76,15 @@
barDatasetSpacing: 1,
data : values
}]
- }
+ };
+ return data;
+ };
- hourData = chartData(#{@commits_per_time.keys.to_json}, #{@commits_per_time.values.to_json})
- responsiveChart($('#hour-chart'), hourData)
+ var hourData = chartData(#{@commits_per_time.keys.to_json}, #{@commits_per_time.values.to_json});
+ responsiveChart($('#hour-chart'), hourData);
- dayData = chartData(#{@commits_per_week_days.keys.to_json}, #{@commits_per_week_days.values.to_json})
- responsiveChart($('#weekday-chart'), dayData)
+ var dayData = chartData(#{@commits_per_week_days.keys.to_json}, #{@commits_per_week_days.values.to_json});
+ responsiveChart($('#weekday-chart'), dayData);
- monthData = chartData(#{@commits_per_month.keys.to_json}, #{@commits_per_month.values.to_json})
- responsiveChart($('#month-chart'), monthData)
+ var monthData = chartData(#{@commits_per_month.keys.to_json}, #{@commits_per_month.values.to_json});
+ responsiveChart($('#month-chart'), monthData);
diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml
index bd342911e49..882e7d6b6ee 100644
--- a/app/views/projects/graphs/show.html.haml
+++ b/app/views/projects/graphs/show.html.haml
@@ -1,9 +1,13 @@
- page_title "Contributors", "Graphs"
= render "header_title"
-.tree-ref-holder
- = render 'shared/ref_switcher', destination: 'graphs'
= render 'head'
+.gray-content-block.append-bottom-default
+ .tree-ref-holder
+ = render 'shared/ref_switcher', destination: 'graphs'
+ %ul.breadcrumb.repo-breadcrumb
+ = commits_breadcrumbs
+
.loading-graph
.center
%h3.page-title
@@ -24,18 +28,21 @@
-:coffeescript
- $.ajax
+:javascript
+ $.ajax({
type: "GET",
url: location.href,
- success: (data) ->
- graph = new ContributorsStatGraph()
- graph.init(data)
+ dataType: "json",
+ success: function (data) {
+ var graph = new ContributorsStatGraph();
+ graph.init(data);
- $("#brush_change").change ->
- graph.change_date_header()
- graph.redraw_authors()
+ $("#brush_change").change(function(){
+ graph.change_date_header();
+ graph.redraw_authors();
+ });
$(".stat-graph").fadeIn();
$(".loading-graph").hide();
- dataType: "json"
+ }
+ });
diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml
index 85dbfd67862..3702aeaecba 100644
--- a/app/views/projects/hooks/index.html.haml
+++ b/app/views/projects/hooks/index.html.haml
@@ -19,7 +19,7 @@
= f.text_field :url, class: "form-control", placeholder: 'http://example.com/trigger-ci.json'
.form-group
= f.label :url, "Trigger", class: 'control-label'
- .col-sm-10
+ .col-sm-10.prepend-top-10
%div
= f.check_box :push_events, class: 'pull-left'
.prepend-left-20
diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml
index f8f2e192e29..92a87690c54 100644
--- a/app/views/projects/imports/new.html.haml
+++ b/app/views/projects/imports/new.html.haml
@@ -17,6 +17,6 @@
This URL must be publicly accessible or you can add a username and password like this: https://username:password@gitlab.com/company/project.git.
%br
The import will time out after 4 minutes. For big repositories, use a clone/push combination.
- For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}
+ For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/importing/migrating_from_svn.html"}
.form-actions
= f.submit 'Start import', class: "btn btn-create", tabindex: 4
diff --git a/app/views/projects/issues/_closed_by_box.html.haml b/app/views/projects/issues/_closed_by_box.html.haml
new file mode 100644
index 00000000000..aef352029d0
--- /dev/null
+++ b/app/views/projects/issues/_closed_by_box.html.haml
@@ -0,0 +1,3 @@
+.issue-closed-by-widget
+ = icon('check')
+ This issue will be closed automatically when merge request #{gfm(merge_requests_sentence(@closed_by_merge_requests.sort))} is accepted.
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index d4a98eca473..c5fd863ae99 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -17,8 +17,10 @@
- @participants.each do |participant|
= link_to_member(@project, participant, name: false, size: 24)
.col-md-3
- %span.slead.has_tooltip{title: 'Cross-project reference'}
- = cross_project_reference(@project, @issue)
+ .input-group.cross-project-reference
+ %span.slead.has_tooltip{title: 'Cross-project reference'}
+ = cross_project_reference(@project, @issue)
+ = clipboard_button
.row
%section.col-md-9
diff --git a/app/views/projects/issues/_issues.html.haml b/app/views/projects/issues/_issues.html.haml
index a3399c57aa2..ca5b1a8386d 100644
--- a/app/views/projects/issues/_issues.html.haml
+++ b/app/views/projects/issues/_issues.html.haml
@@ -5,8 +5,9 @@
.nothing-here-block No issues to show
- if @issues.present?
- .pull-right
- %span.issue_counter #{@issues.total_count}
- issues for this filter
+ .issuable-filter-count
+ %span.pull-right
+ = @issues.total_count
+ issues for this filter
= paginate @issues, theme: "gitlab"
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 5cb814c9ea8..f01bf2505da 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -46,6 +46,7 @@
= markdown(@issue.description)
%textarea.hidden.js-task-list-field
= @issue.description
-
+ - if @closed_by_merge_requests.present?
+ = render 'projects/issues/closed_by_box'
.issue-discussion
= render 'projects/issues/discussion'
diff --git a/app/views/projects/labels/destroy.js.haml b/app/views/projects/labels/destroy.js.haml
index 1b4c83ab097..d59563b122a 100644
--- a/app/views/projects/labels/destroy.js.haml
+++ b/app/views/projects/labels/destroy.js.haml
@@ -1,2 +1,2 @@
- if @project.labels.size == 0
- $('.labels').load(document.URL + ' .light-well').hide().fadeIn(1000)
+ $('.labels').load(document.URL + ' .nothing-here-block').hide().fadeIn(1000)
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 97175f8232b..fb784ee5f4f 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -14,8 +14,8 @@
= render @labels
= paginate @labels, theme: 'gitlab'
- else
- .light-well
+ .nothing-here-block
- if can? current_user, :admin_label, @project
- .nothing-here-block Create first label or #{link_to 'generate', generate_namespace_project_labels_path(@project.namespace, @project), method: :post} default set of labels
+ Create first label or #{link_to 'generate', generate_namespace_project_labels_path(@project.namespace, @project), method: :post} default set of labels
- else
- .nothing-here-block No labels created
+ No labels created
diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml
index 38e66c3828b..7e60782ff5b 100644
--- a/app/views/projects/merge_requests/_discussion.html.haml
+++ b/app/views/projects/merge_requests/_discussion.html.haml
@@ -7,7 +7,7 @@
= render 'shared/show_aside'
-.gray-content-block.second-block
+.gray-content-block.second-block.oneline-block
.row
.col-md-9
.votes-holder.pull-right
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 25e4e8ba80d..c5234c0618c 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -1,3 +1,4 @@
+- ci_commit = merge_request.ci_commit
%li{ class: mr_css_classes(merge_request) }
.merge-request-title
%span.merge-request-title-text
@@ -6,6 +7,8 @@
- merge_request.labels.each do |label|
= link_to_label(label, project: merge_request.project)
.pull-right.light
+ - if ci_commit
+ = render_ci_status(ci_commit)
- if merge_request.merged?
%span
%i.fa.fa-check
@@ -38,6 +41,11 @@
%span
%i.fa.fa-clock-o
= merge_request.milestone.title
+ - if merge_request.target_project.default_branch != merge_request.target_branch
+ &nbsp;
+ %span
+ %i.fa.fa-code-fork
+ = merge_request.target_branch
- if merge_request.tasks?
%span.task-status
= merge_request.task_status
diff --git a/app/views/projects/merge_requests/_merge_requests.html.haml b/app/views/projects/merge_requests/_merge_requests.html.haml
index d86707b3d97..0af970e4b92 100644
--- a/app/views/projects/merge_requests/_merge_requests.html.haml
+++ b/app/views/projects/merge_requests/_merge_requests.html.haml
@@ -5,8 +5,10 @@
.nothing-here-block No merge requests to show
- if @merge_requests.present?
- .pull-right
- %span.cgray.pull-right #{@merge_requests.total_count} merge requests for this filter
+ .issuable-filter-count
+ %span.pull-right
+ = @merge_requests.total_count
+ merge requests for this filter
= paginate @merge_requests, theme: "gitlab"
diff --git a/app/views/projects/merge_requests/_new_compare.html.haml b/app/views/projects/merge_requests/_new_compare.html.haml
index 452006162db..d9eff1f9320 100644
--- a/app/views/projects/merge_requests/_new_compare.html.haml
+++ b/app/views/projects/merge_requests/_new_compare.html.haml
@@ -77,12 +77,13 @@
});
-:coffeescript
-
- $(".merge-request-form").on 'submit', ->
- if $("#merge_request_source_branch").val() is "" or $('#merge_request_target_branch').val() is ""
- $(".mr-compare-errors").html("You must select source and target branch to proceed")
- $(".mr-compare-errors").fadeIn()
- event.preventDefault()
- return
+:javascript
+ $(".merge-request-form").on('submit', function () {
+ if ($("#merge_request_source_branch").val() === "" || $('#merge_request_target_branch').val() === "") {
+ $(".mr-compare-errors").html("You must select source and target branch to proceed");
+ $(".mr-compare-errors").fadeIn();
+ event.preventDefault();
+ return;
+ }
+ });
diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml
index e7ac7a0eaa4..eeaa72ed21b 100644
--- a/app/views/projects/merge_requests/_show.html.haml
+++ b/app/views/projects/merge_requests/_show.html.haml
@@ -36,7 +36,8 @@
- if @merge_request.open? && @merge_request.can_be_merged?
.light.append-bottom-20
You can also accept this merge request manually using the
- = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
+ = succeed '.' do
+ = link_to "command line", "#modal_merge_info", class: "how_to_merge_link vlink", title: "How To Merge", "data-toggle" => "modal"
- if @commits.present?
%ul.merge-request-tabs
diff --git a/app/views/projects/merge_requests/show/_commits.html.haml b/app/views/projects/merge_requests/show/_commits.html.haml
index a71b181a6a5..478054db517 100644
--- a/app/views/projects/merge_requests/show/_commits.html.haml
+++ b/app/views/projects/merge_requests/show/_commits.html.haml
@@ -1 +1,5 @@
+.gray-content-block.second-block.oneline-block
+ = icon("sort-amount-desc")
+ Most recent commits displayed first
+
= render "projects/commits/commits", project: @merge_request.project
diff --git a/app/views/projects/merge_requests/show/_diffs.html.haml b/app/views/projects/merge_requests/show/_diffs.html.haml
index 626970f39be..d9cfc3d7ae9 100644
--- a/app/views/projects/merge_requests/show/_diffs.html.haml
+++ b/app/views/projects/merge_requests/show/_diffs.html.haml
@@ -1,5 +1,5 @@
- if @merge_request_diff.collected?
- = render "projects/diffs/diffs", diffs: @merge_request.diffs, project: @merge_request.project
+ = render "projects/diffs/diffs", diffs: params[:w] == '1' ? @merge_request.diffs_no_whitespace : @merge_request.diffs, project: @merge_request.project
- elsif @merge_request_diff.empty?
.nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch}
- else
diff --git a/app/views/projects/merge_requests/show/_how_to_merge.html.haml b/app/views/projects/merge_requests/show/_how_to_merge.html.haml
index f18cf96c17d..98f0357ce4e 100644
--- a/app/views/projects/merge_requests/show/_how_to_merge.html.haml
+++ b/app/views/projects/merge_requests/show/_how_to_merge.html.haml
@@ -3,11 +3,12 @@
.modal-content
.modal-header
%a.close{href: "#", "data-dismiss" => "modal"} ×
- %h3 Check out, review and merge locally
+ %h3 Check out, review, and merge locally
.modal-body
%p
- %strong Step 1.
+ %strong Step 1.
Fetch and check out the branch for this merge request
+ = clipboard_button
%pre.dark
- if @merge_request.for_fork?
:preserve
@@ -24,6 +25,7 @@
%p
%strong Step 3.
Merge the branch and fix any conflicts that come up
+ = clipboard_button
%pre.dark
- if @merge_request.for_fork?
:preserve
@@ -36,6 +38,7 @@
%p
%strong Step 4.
Push the result of the merge to GitLab
+ = clipboard_button
%pre.dark
:preserve
git push origin #{h @merge_request.target_branch}
diff --git a/app/views/projects/merge_requests/widget/_heading.html.haml b/app/views/projects/merge_requests/widget/_heading.html.haml
index 68dda1424cf..ba5ad22bca7 100644
--- a/app/views/projects/merge_requests/widget/_heading.html.haml
+++ b/app/views/projects/merge_requests/widget/_heading.html.haml
@@ -1,44 +1,44 @@
-- if @merge_request.has_ci?
- - ci_commit = @merge_request.source_project.ci_commit(@merge_request.source_sha)
- - if ci_commit
- - status = ci_commit.status
- .mr-widget-heading
- .ci_widget{class: "ci-#{status}"}
- = ci_status_icon(ci_commit)
+- ci_commit = @merge_request.ci_commit
+- if ci_commit
+ - status = ci_commit.status
+ .mr-widget-heading
+ .ci_widget{class: "ci-#{status}"}
+ = ci_status_icon(ci_commit)
+ %span CI build #{status}
+ for #{@merge_request.last_commit_short_sha}.
+ %span.ci-coverage
+ = link_to "View build details", ci_status_path(ci_commit)
+
+- elsif @merge_request.has_ci?
+ - # Compatibility with old CI integrations (ex jenkins) when you request status from CI server via AJAX
+ - # Remove in later versions when services like Jenkins will set CI status via Commit status API
+ .mr-widget-heading
+ - [:success, :skipped, :canceled, :failed, :running, :pending].each do |status|
+ .ci_widget{class: "ci-#{status}", style: "display:none"}
+ - if status == :success
+ - status = "passed"
+ = icon("check-circle")
+ - else
+ = icon("circle")
%span CI build #{status}
for #{@merge_request.last_commit_short_sha}.
%span.ci-coverage
- = link_to "View build details", ci_status_path(ci_commit)
-
- - else
- - # Compatibility with old CI integrations (ex jenkins) when you request status from CI server via AJAX
- - # Remove in later versions when services like Jenkins will set CI status via Commit status API
- .mr-widget-heading
- - [:success, :skipped, :canceled, :failed, :running, :pending].each do |status|
- .ci_widget{class: "ci-#{status}", style: "display:none"}
- - if status == :success
- - status = "passed"
- = icon("check-circle")
- - else
- = icon("circle")
- %span CI build #{status}
- for #{@merge_request.last_commit_short_sha}.
- %span.ci-coverage
- - if ci_build_details_path(@merge_request)
- = link_to "View build details", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
+ - if ci_build_details_path(@merge_request)
+ = link_to "View build details", ci_build_details_path(@merge_request), :"data-no-turbolink" => "data-no-turbolink"
- .ci_widget
- = icon("spinner spin")
- Checking CI status for #{@merge_request.last_commit_short_sha}&hellip;
+ .ci_widget
+ = icon("spinner spin")
+ Checking CI status for #{@merge_request.last_commit_short_sha}&hellip;
- .ci_widget.ci-not_found{style: "display:none"}
- = icon("times-circle")
- Could not find CI status for #{@merge_request.last_commit_short_sha}.
+ .ci_widget.ci-not_found{style: "display:none"}
+ = icon("times-circle")
+ Could not find CI status for #{@merge_request.last_commit_short_sha}.
- .ci_widget.ci-error{style: "display:none"}
- = icon("times-circle")
- Could not connect to the CI server. Please check your settings and try again.
+ .ci_widget.ci-error{style: "display:none"}
+ = icon("times-circle")
+ Could not connect to the CI server. Please check your settings and try again.
- :coffeescript
- $ ->
- merge_request_widget.getCiStatus()
+ :javascript
+ $(function() {
+ merge_request_widget.getCiStatus();
+ });
diff --git a/app/views/projects/merge_requests/widget/_merged.html.haml b/app/views/projects/merge_requests/widget/_merged.html.haml
index f223f687def..a788fcea23f 100644
--- a/app/views/projects/merge_requests/widget/_merged.html.haml
+++ b/app/views/projects/merge_requests/widget/_merged.html.haml
@@ -15,7 +15,7 @@
- elsif can_remove_branch?(@merge_request.source_project, @merge_request.source_branch)
.remove_source_branch_widget
- %p
+ %p
= succeed '.' do
The changes were merged into
%span.label-branch= @merge_request.target_branch
@@ -25,7 +25,7 @@
Remove Source Branch
.remove_source_branch_widget.failed.hide
- %p
+ %p
Failed to remove source branch '#{@merge_request.source_branch}'.
.remove_source_branch_in_progress.hide
@@ -33,17 +33,20 @@
= icon('spinner spin')
Removing source branch '#{@merge_request.source_branch}'. Please wait. This page will be automatically reload.
- :coffeescript
- $('.remove_source_branch').on 'click', ->
- $('.remove_source_branch_widget').hide()
- $('.remove_source_branch_in_progress').show()
-
- $(".remove_source_branch").on "ajax:success", (e, data, status, xhr) ->
- location.reload()
-
- $(".remove_source_branch").on "ajax:error", (e, data, status, xhr) ->
- $('.remove_source_branch_widget').hide()
- $('.remove_source_branch_in_progress').hide()
- $('.remove_source_branch_widget.failed').show()
+ :javascript
+ $('.remove_source_branch').on('click', function() {
+ $('.remove_source_branch_widget').hide();
+ $('.remove_source_branch_in_progress').show();
+ });
+
+ $(".remove_source_branch").on("ajax:success", function (e, data, status, xhr) {
+ location.reload();
+ });
+
+ $(".remove_source_branch").on("ajax:error", function (e, data, status, xhr) {
+ $('.remove_source_branch_widget').hide();
+ $('.remove_source_branch_in_progress').hide();
+ $('.remove_source_branch_widget.failed').show();
+ });
diff --git a/app/views/projects/merge_requests/widget/open/_accept.html.haml b/app/views/projects/merge_requests/widget/open/_accept.html.haml
index 613525437ab..9b31014b581 100644
--- a/app/views/projects/merge_requests/widget/open/_accept.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_accept.html.haml
@@ -1,8 +1,10 @@
+- status_class = @merge_request.ci_commit ? " ci-#{@merge_request.ci_commit.status}" : nil
+
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-requires-input' } do |f|
= hidden_field_tag :authenticity_token, form_authenticity_token
.accept-merge-holder.clearfix.js-toggle-container
.accept-action
- = f.button class: "btn btn-create accept_merge_request" do
+ = f.button class: "btn btn-create accept_merge_request#{status_class}" do
Accept Merge Request
- if can_remove_branch?(@merge_request.source_project, @merge_request.source_branch) && !@merge_request.for_fork?
.accept-control.checkbox
@@ -18,8 +20,9 @@
text: @merge_request.merge_commit_message,
rows: 14, hint: true
- :coffeescript
- $('.accept-mr-form').on 'ajax:before', ->
- btn = $('.accept_merge_request')
- btn.disable()
- btn.html("<i class='fa fa-spinner fa-spin'></i> Merge in progress")
+ :javascript
+ $('.accept-mr-form').on('ajax:before', function() {
+ var btn = $('.accept_merge_request');
+ btn.disable();
+ btn.html("<i class='fa fa-spinner fa-spin'></i> Merge in progress");
+ });
diff --git a/app/views/projects/merge_requests/widget/open/_check.html.haml b/app/views/projects/merge_requests/widget/open/_check.html.haml
index b6b8974297e..e16878ba513 100644
--- a/app/views/projects/merge_requests/widget/open/_check.html.haml
+++ b/app/views/projects/merge_requests/widget/open/_check.html.haml
@@ -2,6 +2,8 @@
= icon("spinner spin")
Checking ability to merge automatically&hellip;
-:coffeescript
- $ ->
- merge_request_widget.getMergeStatus()
+:javascript
+ $(function() {
+ merge_request_widget.getMergeStatus();
+ });
+
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index 255ddab479f..24879b19d2b 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -23,9 +23,7 @@
.col-sm-10
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do
= render 'projects/zen', f: f, attr: :description, classes: 'description form-control js-quick-submit'
- .hint
- .pull-left Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}.
- .pull-left Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+ = render 'projects/notes/hints'
.clearfix
.error-alert
.col-md-6
@@ -45,7 +43,7 @@
:javascript
- $( ".datepicker" ).datepicker({
+ $(".datepicker").datepicker({
dateFormat: "yy-mm-dd",
onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
}).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val()));
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index daab2326bc7..a02c12f06a8 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -124,9 +124,11 @@
Creating project &amp; repository.
%p Please wait a moment, this page will automatically refresh when ready.
-:coffeescript
- $('.how_to_import_link').bind 'click', (e) ->
- e.preventDefault()
- import_modal = $(this).next(".modal").show()
- $('.modal-header .close').bind 'click', ->
- $(".modal").hide()
+:javascript
+ $('.how_to_import_link').bind('click', function (e) {
+ e.preventDefault();
+ var import_modal = $(this).next(".modal").show();
+ });
+ $('.modal-header .close').bind('click', function() {
+ $(".modal").hide();
+ });
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index 5d184730796..88808301985 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -2,7 +2,7 @@
.timeline-entry-inner
.timeline-icon
%a{href: user_path(note.author)}
- %img.avatar.s40{src: avatar_icon(note.author), alt: ''}
+ = image_tag avatar_icon(note.author), alt: '', class: 'avatar s40'
.timeline-content
.note-header
- if note_editable?(note)
diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml
index 82809bec5b8..9fc4be583cc 100644
--- a/app/views/projects/project_members/index.html.haml
+++ b/app/views/projects/project_members/index.html.haml
@@ -29,7 +29,8 @@
- if @group
= render "group_members", members: @group_members
-:coffeescript
- $('form.member-search-form').on 'submit', (event) ->
- event.preventDefault()
- Turbolinks.visit @.action + '?' + $(@).serialize()
+:javascript
+ $('form.member-search-form').on('submit', function (event) {
+ event.preventDefault();
+ Turbolinks.visit(this.action + '?' + $(this).serialize());
+ });
diff --git a/app/views/projects/protected_branches/_branches_list.html.haml b/app/views/projects/protected_branches/_branches_list.html.haml
index bb49f4de873..f68449b1863 100644
--- a/app/views/projects/protected_branches/_branches_list.html.haml
+++ b/app/views/projects/protected_branches/_branches_list.html.haml
@@ -1,34 +1,35 @@
- unless @branches.empty?
%br
%h4 Already Protected:
- %table.table.protected-branches-list
- %thead
- %tr.no-border
- %th Branch
- %th Developers can push
- %th Last commit
- %th
+ .table-holder
+ %table.table.protected-branches-list
+ %thead
+ %tr.no-border
+ %th Branch
+ %th Developers can push
+ %th Last commit
+ %th
- %tbody
- - @branches.each do |branch|
- - @url = namespace_project_protected_branch_path(@project.namespace, @project, branch)
- %tr
- %td
- = link_to namespace_project_commits_path(@project.namespace, @project, branch.name) do
- %strong= branch.name
- - if @project.root_ref?(branch.name)
- %span.label.label-info default
+ %tbody
+ - @branches.each do |branch|
+ - @url = namespace_project_protected_branch_path(@project.namespace, @project, branch)
+ %tr
%td
- = check_box_tag "developers_can_push", branch.id, branch.developers_can_push, "data-url" => @url
- %td
- - if commit = branch.commit
- = link_to namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id' do
- = commit.short_id
- &middot;
- #{time_ago_with_tooltip(commit.committed_date)}
- - else
- (branch was removed from repository)
- %td
- .pull-right
- - if can? current_user, :admin_project, @project
- = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-remove btn-sm"
+ = link_to namespace_project_commits_path(@project.namespace, @project, branch.name) do
+ %strong= branch.name
+ - if @project.root_ref?(branch.name)
+ %span.label.label-info default
+ %td
+ = check_box_tag "developers_can_push", branch.id, branch.developers_can_push, "data-url" => @url
+ %td
+ - if commit = branch.commit
+ = link_to namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id' do
+ = commit.short_id
+ &middot;
+ #{time_ago_with_tooltip(commit.committed_date)}
+ - else
+ (branch was removed from repository)
+ %td
+ .pull-right
+ - if can? current_user, :admin_project, @project
+ = link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-remove btn-sm"
diff --git a/app/views/projects/releases/edit.html.haml b/app/views/projects/releases/edit.html.haml
new file mode 100644
index 00000000000..e7db09cdaa9
--- /dev/null
+++ b/app/views/projects/releases/edit.html.haml
@@ -0,0 +1,20 @@
+- page_title "Edit", @tag.name, "Tags"
+= render "projects/commits/header_title"
+= render "projects/commits/head"
+
+.gray-content-block
+ .oneline
+ .title
+ Release notes for tag
+ %strong #{@tag.name}
+
+.prepend-top-default
+ = form_for(@release, method: :put, url: namespace_project_tag_release_path(@project.namespace, @project, @tag.name), html: { class: 'form-horizontal gfm-form release-form' }) do |f|
+ = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
+ = render 'projects/zen', f: f, attr: :description, classes: 'description js-quick-submit'
+ = render 'projects/notes/hints'
+ .error-alert
+ .prepend-top-default
+ = f.submit 'Save changes', class: 'btn btn-save'
+ = link_to "Cancel", namespace_project_tag_path(@project.namespace, @project, @tag.name), class: "btn btn-default btn-cancel"
+
diff --git a/app/views/projects/remove_fork.js.haml b/app/views/projects/remove_fork.js.haml
new file mode 100644
index 00000000000..17b9fecfeb1
--- /dev/null
+++ b/app/views/projects/remove_fork.js.haml
@@ -0,0 +1,2 @@
+:plain
+ location.href = "#{edit_namespace_project_path(@project.namespace, @project)}";
diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml
index 66851d38316..dde9e448cb9 100644
--- a/app/views/projects/runners/edit.html.haml
+++ b/app/views/projects/runners/edit.html.haml
@@ -1,3 +1,5 @@
+- page_title "Edit", "#{@runner.description} ##{@runner.id}", "Runners"
+
%h4 Runner ##{@runner.id}
%hr
= form_for @runner, url: runner_path(@runner), html: { class: 'form-horizontal' } do |f|
diff --git a/app/views/projects/runners/index.html.haml b/app/views/projects/runners/index.html.haml
index 529fb9c296d..315afe4a764 100644
--- a/app/views/projects/runners/index.html.haml
+++ b/app/views/projects/runners/index.html.haml
@@ -1,3 +1,4 @@
+- page_title "Runners"
.light
%p
A 'runner' is a process which runs a build.
diff --git a/app/views/projects/runners/show.html.haml b/app/views/projects/runners/show.html.haml
index ffec495f85a..5bf4c09ca25 100644
--- a/app/views/projects/runners/show.html.haml
+++ b/app/views/projects/runners/show.html.haml
@@ -1,64 +1,66 @@
-= content_for :title do
- %h3.project-title
- Runner ##{@runner.id}
- .pull-right
- - if @runner.shared?
- %span.runner-state.runner-state-shared
- Shared
- - else
- %span.runner-state.runner-state-specific
- Specific
+- page_title "#{@runner.description} ##{@runner.id}", "Runners"
-%table.table
- %thead
+%h3.page-title
+ Runner ##{@runner.id}
+ .pull-right
+ - if @runner.shared?
+ %span.runner-state.runner-state-shared
+ Shared
+ - else
+ %span.runner-state.runner-state-specific
+ Specific
+
+.table-holder
+ %table.table
+ %thead
+ %tr
+ %th Property Name
+ %th Value
+ %tr
+ %td
+ Tags
+ %td
+ - @runner.tag_list.each do |tag|
+ %span.label.label-primary
+ = tag
+ %tr
+ %td
+ Name
+ %td
+ = @runner.name
+ %tr
+ %td
+ Version
+ %td
+ = @runner.version
+ %tr
+ %td
+ Revision
+ %td
+ = @runner.revision
+ %tr
+ %td
+ Platform
+ %td
+ = @runner.platform
+ %tr
+ %td
+ Architecture
+ %td
+ = @runner.architecture
+ %tr
+ %td
+ Description
+ %td
+ = @runner.description
%tr
- %th Property Name
- %th Value
- %tr
- %td
- Tags
- %td
- - @runner.tag_list.each do |tag|
- %span.label.label-primary
- = tag
- %tr
- %td
- Name
- %td
- = @runner.name
- %tr
- %td
- Version
- %td
- = @runner.version
- %tr
- %td
- Revision
- %td
- = @runner.revision
- %tr
- %td
- Platform
- %td
- = @runner.platform
- %tr
- %td
- Architecture
- %td
- = @runner.architecture
- %tr
- %td
- Description
- %td
- = @runner.description
- %tr
- %td
- Last contact
- %td
- - if @runner.contacted_at
- #{time_ago_in_words(@runner.contacted_at)} ago
- - else
- Never
+ %td
+ Last contact
+ %td
+ - if @runner.contacted_at
+ #{time_ago_in_words(@runner.contacted_at)} ago
+ - else
+ Never
-
+
diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/index.html.haml
index 1065def693b..c1356f6db02 100644
--- a/app/views/projects/services/index.html.haml
+++ b/app/views/projects/services/index.html.haml
@@ -2,22 +2,23 @@
%h3.page-title Project services
%p.light Project services allow you to integrate GitLab with other applications
-%table.table
- %thead
- %tr
- %th
- %th Service
- %th Description
- %th Last edit
- - @services.sort_by(&:title).each do |service|
- %tr
- %td
- = boolean_to_icon service.activated?
- %td
- = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do
- %strong= service.title
- %td
- = service.description
- %td.light
- = time_ago_in_words service.updated_at
- ago
+.table-holder
+ %table.table
+ %thead
+ %tr
+ %th
+ %th Service
+ %th Description
+ %th Last edit
+ - @services.sort_by(&:title).each do |service|
+ %tr
+ %td
+ = boolean_to_icon service.activated?
+ %td
+ = link_to edit_namespace_project_service_path(@project.namespace, @project, service.to_param) do
+ %strong= service.title
+ %td
+ = service.description
+ %td.light
+ = time_ago_in_words service.updated_at
+ ago
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index e95d987d74c..585caf674c9 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -7,8 +7,7 @@
= render 'shared/no_ssh'
= render 'shared/no_password'
-- if prefer_readme?
- = render 'projects/last_push'
+= render 'projects/last_push'
= render "home_panel"
@@ -28,7 +27,7 @@
= link_to project_files_path(@project) do
= repository_size
- - if !prefer_readme? && @repository.readme
+ - if default_project_view != 'readme' && @repository.readme
%li
= link_to 'Readme', readme_path(@project)
@@ -64,14 +63,12 @@
= icon("exclamation-triangle fw")
Archived project! Repository is read-only
-%section
- - if prefer_readme?
- .project-show-readme
- = render 'projects/readme'
- - else
- .project-show-activity
- = render 'projects/activity'
+- if @repository.commit
+ .content-block.second-block.white
+ = render 'projects/last_commit', commit: @repository.commit, project: @project
+%div{class: "project-show-#{default_project_view}"}
+ = render default_project_view
- if current_user
- access = user_max_access_in_project(current_user, @project)
diff --git a/app/views/projects/snippets/_actions.html.haml b/app/views/projects/snippets/_actions.html.haml
new file mode 100644
index 00000000000..4a515469422
--- /dev/null
+++ b/app/views/projects/snippets/_actions.html.haml
@@ -0,0 +1,11 @@
+= link_to new_namespace_project_snippet_path(@project.namespace, @project), class: 'btn btn-grouped new-snippet-link', title: "New Snippet" do
+ = icon('plus')
+ New Snippet
+- if can?(current_user, :admin_project_snippet, @snippet)
+ = link_to namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-remove", title: 'Delete Snippet' do
+ = icon('trash-o')
+ Delete
+- if can?(current_user, :update_project_snippet, @snippet)
+ = link_to edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-grouped snippable-edit" do
+ = icon('pencil-square-o')
+ Edit
diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml
index 3fed2c9949d..4af963e14da 100644
--- a/app/views/projects/snippets/index.html.haml
+++ b/app/views/projects/snippets/index.html.haml
@@ -1,17 +1,13 @@
- page_title "Snippets"
= render "header_title"
-%h3.page-title
- Snippets
- - if can? current_user, :create_project_snippet, @project
- = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new pull-right", title: "New Snippet" do
- Add new snippet
+.gray-content-block.top-block
+ .pull-right
+ = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "New Snippet" do
+ = icon('plus')
+ New Snippet
-%p.light
- Share code pastes with others out of git repository
+ .oneline
+ Share code pastes with others out of git repository
-%ul.bordered-list
- = render partial: "shared/snippets/snippet", collection: @snippets
- - if @snippets.empty?
- %li
- .nothing-here-block Nothing here.
+= render 'snippets/snippets'
diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml
index be7d4d486fa..5d706942f2d 100644
--- a/app/views/projects/snippets/show.html.haml
+++ b/app/views/projects/snippets/show.html.haml
@@ -1,40 +1,18 @@
- page_title @snippet.title, "Snippets"
= render "header_title"
-%h3.page-title
- = @snippet.title
+.snippet-holder
+ = render 'shared/snippets/header'
- .pull-right
- = link_to new_namespace_project_snippet_path(@project.namespace, @project), class: "btn btn-new", title: "New Snippet" do
- Add new snippet
+ %article.file-holder
+ .file-title
+ = blob_icon 0, @snippet.file_name
+ %strong
+ = @snippet.file_name
+ .file-actions.hidden-xs
+ .btn-group.tree-btn-group
+ = link_to 'Raw', raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank"
-%hr
+ = render 'shared/snippets/blob'
-.append-bottom-20
- .pull-right
- = "##{@snippet.id}"
- %span.light
- by
- = link_to user_path(@snippet.author) do
- = image_tag avatar_icon(@snippet.author_email), class: "avatar avatar-inline s16"
- = @snippet.author_name
-
- .back-link
- = link_to namespace_project_snippets_path(@project.namespace, @project) do
- &larr; project snippets
-
-.file-holder
- .file-title
- %i.fa.fa-file
- %strong
- = @snippet.file_name
- .file-actions
- .btn-group
- - if can?(current_user, :update_project_snippet, @snippet)
- = link_to "edit", edit_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", title: 'Edit Snippet'
- = link_to "raw", raw_namespace_project_snippet_path(@project.namespace, @project, @snippet), class: "btn btn-sm", target: "_blank"
- - if can?(current_user, :admin_project_snippet, @snippet)
- = link_to "remove", namespace_project_snippet_path(@project.namespace, @project, @snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-sm btn-remove", title: 'Delete Snippet'
- = render 'shared/snippets/blob'
-
-%div#notes= render "projects/notes/notes_with_form"
+ %div#notes= render "projects/notes/notes_with_form"
diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml
new file mode 100644
index 00000000000..667057ef2d8
--- /dev/null
+++ b/app/views/projects/tags/_download.html.haml
@@ -0,0 +1,17 @@
+%span.btn-group.btn-grouped
+ = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'zip'), class: 'btn btn-default', rel: 'nofollow' do
+ %i.fa.fa-download
+ %span source code
+ %a.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown' }
+ %span.caret
+ %span.sr-only
+ Select Archive Format
+ %ul.col-xs-10.dropdown-menu{ role: 'menu' }
+ %li
+ = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'zip'), rel: 'nofollow' do
+ %i.fa.fa-download
+ %span Download zip
+ %li
+ = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do
+ %i.fa.fa-download
+ %span Download tar.gz
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index 2ca295fc5f3..e2c5178185e 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -1,22 +1,28 @@
- commit = @repository.commit(tag.target)
+- release = @releases.find { |release| release.tag == tag.name }
%li
%div
- = link_to namespace_project_commits_path(@project.namespace, @project, tag.name), class: "" do
+ = link_to namespace_project_tag_path(@project.namespace, @project, tag.name) do
%strong
- %i.fa.fa-tag
+ = icon('tag')
= tag.name
- if tag.message.present?
&nbsp;
= strip_gpg_signature(tag.message)
+
.controls
+ = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, tag.name), class: 'btn-grouped btn' do
+ = icon("pencil")
- if can? current_user, :download_code, @project
- = render 'projects/repositories/download_archive', ref: tag.name, btn_class: 'btn-grouped btn-group-xs'
- - if can?(current_user, :admin_project, @project)
- = link_to namespace_project_tag_path(@project.namespace, @project, tag.name), class: 'btn btn-xs btn-remove remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'}, remote: true do
- %i.fa.fa-trash-o
+ = render 'projects/tags/download', ref: tag.name, project: @project
- if commit
= render 'projects/branches/commit', commit: commit, project: @project
- else
%p
Cant find HEAD commit for this tag
+ - if release && release.description.present?
+ .description.prepend-top-default
+ .wiki
+ = preserve do
+ = markdown release.description
diff --git a/app/views/projects/tags/destroy.js.haml b/app/views/projects/tags/destroy.js.haml
deleted file mode 100644
index ada6710f940..00000000000
--- a/app/views/projects/tags/destroy.js.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-$('.js-totaltags-count').html("#{@repository.tags.size}")
-- if @repository.tags.size == 0
- $('.tags').load(document.URL + ' .nothing-here-block').hide().fadeIn(1000)
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index 9f5c1be125c..e106be794f1 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -5,10 +5,12 @@
.alert.alert-danger
%button{ type: "button", class: "close", "data-dismiss" => "alert"} &times;
= @error
+
%h3.page-title
- %i.fa.fa-code-fork
- New tag
-= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal" do
+ New git tag
+%hr
+
+= form_tag namespace_project_tags_path, method: :post, id: "new-tag-form", class: "form-horizontal tag-form" do
.form-group
= label_tag :tag_name, 'Name for new tag', class: 'control-label'
.col-sm-10
@@ -17,12 +19,29 @@
= label_tag :ref, 'Create from', class: 'control-label'
.col-sm-10
= text_field_tag :ref, params[:ref], placeholder: 'master', required: true, tabindex: 2, class: 'form-control'
- .light Branch name or commit SHA
+ .help-block Branch name or commit SHA
.form-group
= label_tag :message, 'Message', class: 'control-label'
.col-sm-10
= text_field_tag :message, nil, placeholder: 'Enter message.', required: false, tabindex: 3, class: 'form-control'
- .light (Optional) Entering a message will create an annotated tag.
+ .help-block (Optional) Entering a message will create an annotated tag.
+ %hr
+ .form-group
+ = label_tag :release_description, 'Release notes', class: 'control-label'
+ .col-sm-10
+ = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
+ .zennable
+ %input#zen-toggle-comment.zen-toggle-comment(tabindex="-1" type="checkbox")
+ .zen-backdrop
+ = text_area_tag :release_description, nil, class: 'js-gfm-input markdown-area description js-quick-submit form-control', placeholder: ''
+ %a.zen-enter-link(tabindex="-1" href="#")
+ = icon('expand')
+ Edit in fullscreen
+ %a.zen-leave-link(href="#")
+ = icon('compress')
+
+ = render 'projects/notes/hints'
+ .help-block (Optional) You can add release notes to your tag. It will be stored in the GitLab database and shown on the tags page
.form-actions
= button_tag 'Create tag', class: 'btn btn-create', tabindex: 3
= link_to 'Cancel', namespace_project_tags_path(@project.namespace, @project), class: 'btn btn-cancel'
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
new file mode 100644
index 00000000000..ebe3718afcc
--- /dev/null
+++ b/app/views/projects/tags/show.html.haml
@@ -0,0 +1,39 @@
+- page_title @tag.name, "Tags"
+= render "projects/commits/header_title"
+= render "projects/commits/head"
+
+.gray-content-block
+ .pull-right
+ - if can?(current_user, :push_code, @project)
+ = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, @tag.name), class: 'btn-grouped btn', title: 'Edit release notes' do
+ = icon("pencil")
+ = link_to namespace_project_tree_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped', title: 'Browse source code' do
+ = icon('files-o')
+ = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn btn-grouped', title: 'Browse commits' do
+ = icon('history')
+ - if can? current_user, :download_code, @project
+ = render 'projects/tags/download', ref: @tag.name, project: @project
+ - if can?(current_user, :admin_project, @project)
+ .pull-right
+ = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped', method: :delete, data: { confirm: 'Removed tag cannot be restored. Are you sure?'} do
+ %i.fa.fa-trash-o
+ .title
+ %strong= @tag.name
+ - if @tag.message.present?
+ %span.light
+ &nbsp;
+ = strip_gpg_signature(@tag.message)
+ - if @commit
+ = render 'projects/branches/commit', commit: @commit, project: @project
+ - else
+ Cant find HEAD commit for this tag
+
+
+.append-bottom-default.prepend-top-default
+ - if @release.description.present?
+ .description
+ .wiki
+ = preserve do
+ = markdown @release.description
+ - else
+ This tag has no release notes.
diff --git a/app/views/projects/tree/_blob_item.html.haml b/app/views/projects/tree/_blob_item.html.haml
index 02ecbade219..2ddc5d504fa 100644
--- a/app/views/projects/tree/_blob_item.html.haml
+++ b/app/views/projects/tree/_blob_item.html.haml
@@ -4,5 +4,5 @@
%span.str-truncated
= link_to blob_item.name, namespace_project_blob_path(@project.namespace, @project, tree_join(@id || @commit.id, blob_item.name))
%td.tree_time_ago.cgray
- = render 'spinner'
+ = render 'projects/tree/spinner'
%td.hidden-xs.tree_commit
diff --git a/app/views/projects/tree/_readme.html.haml b/app/views/projects/tree/_readme.html.haml
index 7e9af19c8ba..3c5edf4b033 100644
--- a/app/views/projects/tree/_readme.html.haml
+++ b/app/views/projects/tree/_readme.html.haml
@@ -1,8 +1,8 @@
-%article.file-holder.readme-holder#README
+%article.file-holder.readme-holder
.file-title
- = link_to '#README' do
+ = blob_icon readme.mode, readme.name
+ = link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@repository.root_ref, readme.name)) do
%strong
- %i.fa.fa-file
= readme.name
.file-content.wiki
= render_readme(readme)
diff --git a/app/views/projects/tree/_tree.html.haml b/app/views/projects/tree/_tree_content.html.haml
index 7ff48e32e60..ee4c9d1693d 100644
--- a/app/views/projects/tree/_tree.html.haml
+++ b/app/views/projects/tree/_tree_content.html.haml
@@ -1,36 +1,5 @@
-.gray-content-block
- %ul.breadcrumb.repo-breadcrumb
- %li
- = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
- = @project.path
- - tree_breadcrumbs(tree, 6) do |title, path|
- %li
- - if path
- = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
- - else
- = link_to title, '#'
- - if allowed_tree_edit?
- %li
- %span.dropdown
- %a.dropdown-toggle.btn.add-to-tree{href: '#', "data-toggle" => "dropdown"}
- = icon('plus')
- %ul.dropdown-menu
- %li
- = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'Create file', id: 'new-file-link' do
- = icon('pencil fw')
- Create file
- %li
- = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do
- = icon('file fw')
- Upload file
- %li.divider
- %li
- = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do
- = icon('folder fw')
- New directory
-
-%div#tree-content-holder.tree-content-holder
- .tree-table-holder
+%div.tree-content-holder
+ .table-holder
%table.table#tree-slider{class: "table_#{@hex_path} tree-table table-striped" }
%thead
%tr
@@ -60,8 +29,6 @@
- if tree.readme
= render "projects/tree/readme", readme: tree.readme
-%div.tree_progress
-
- if allowed_tree_edit?
= render 'projects/blob/upload', title: 'Upload', placeholder: 'Upload new file', button_title: 'Upload file', form_path: namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post
= render 'projects/blob/new_dir'
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
new file mode 100644
index 00000000000..1115ca6b4ca
--- /dev/null
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -0,0 +1,32 @@
+.tree-ref-holder
+ = render 'shared/ref_switcher', destination: 'tree', path: @path
+
+%ul.breadcrumb.repo-breadcrumb
+ %li
+ = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do
+ = @project.path
+ - tree_breadcrumbs(tree, 6) do |title, path|
+ %li
+ - if path
+ = link_to truncate(title, length: 40), namespace_project_tree_path(@project.namespace, @project, path)
+ - else
+ = link_to title, '#'
+ - if allowed_tree_edit?
+ %li
+ %span.dropdown
+ %a.dropdown-toggle.btn.add-to-tree{href: '#', "data-toggle" => "dropdown"}
+ = icon('plus')
+ %ul.dropdown-menu
+ %li
+ = link_to namespace_project_new_blob_path(@project.namespace, @project, @id), title: 'Create file', id: 'new-file-link' do
+ = icon('pencil fw')
+ Create file
+ %li
+ = link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal'} do
+ = icon('file fw')
+ Upload file
+ %li.divider
+ %li
+ = link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal'} do
+ = icon('folder fw')
+ New directory
diff --git a/app/views/projects/tree/_tree_item.html.haml b/app/views/projects/tree/_tree_item.html.haml
index e87138bf980..cf65057e704 100644
--- a/app/views/projects/tree/_tree_item.html.haml
+++ b/app/views/projects/tree/_tree_item.html.haml
@@ -5,5 +5,5 @@
- path = flatten_tree(tree_item)
= link_to path, namespace_project_tree_path(@project.namespace, @project, tree_join(@id || @commit.id, path))
%td.tree_time_ago.cgray
- = render 'spinner'
+ = render 'projects/tree/spinner'
%td.hidden-xs.tree_commit
diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml
index dec4677f830..ec14bd7f65a 100644
--- a/app/views/projects/tree/show.html.haml
+++ b/app/views/projects/tree/show.html.haml
@@ -6,12 +6,12 @@
= render 'projects/last_push'
-.tree-ref-holder
- = render 'shared/ref_switcher', destination: 'tree', path: @path
-
- if can? current_user, :download_code, @project
.tree-download-holder
= render 'projects/repositories/download_archive', ref: @ref, btn_class: 'btn-group pull-right hidden-xs hidden-sm', split_button: true
#tree-holder.tree-holder.clearfix
- = render "tree", tree: @tree
+ .gray-content-block.top-block
+ = render 'projects/tree/tree_header', tree: @tree
+
+ = render 'projects/tree/tree_content', tree: @tree
diff --git a/app/views/projects/triggers/index.html.haml b/app/views/projects/triggers/index.html.haml
index 17dcb78e256..b3ad79a200e 100644
--- a/app/views/projects/triggers/index.html.haml
+++ b/app/views/projects/triggers/index.html.haml
@@ -1,3 +1,4 @@
+- page_title "Triggers"
%h3.page-title
Triggers
@@ -7,12 +8,13 @@
%hr.clearfix
-if @triggers.any?
- %table.table
- %thead
- %th Token
- %th Last used
- %th
- = render partial: 'trigger', collection: @triggers, as: :trigger
+ .table-holder
+ %table.table
+ %thead
+ %th Token
+ %th Last used
+ %th
+ = render partial: 'trigger', collection: @triggers, as: :trigger
- else
%h4 No triggers
diff --git a/app/views/projects/variables/show.html.haml b/app/views/projects/variables/show.html.haml
index 29416a94ff6..e052da1ac43 100644
--- a/app/views/projects/variables/show.html.haml
+++ b/app/views/projects/variables/show.html.haml
@@ -1,3 +1,4 @@
+- page_title "Variables"
%h3.page-title
Secret Variables
diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml
index 261d4a92d7d..9c94c43e747 100644
--- a/app/views/projects/wikis/_form.html.haml
+++ b/app/views/projects/wikis/_form.html.haml
@@ -23,9 +23,7 @@
.col-sm-10
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview" } do
= render 'projects/zen', f: f, attr: :content, classes: 'description form-control js-quick-submit'
- .col-sm-12.hint
- .pull-left Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"), target: '_blank'}
- .pull-right Attach files by dragging &amp; dropping or #{link_to "selecting them", '#', class: 'markdown-selector' }.
+ = render 'projects/notes/hints'
.clearfix
.error-alert
diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml
index bfbef823b35..4322146ce34 100644
--- a/app/views/projects/wikis/history.html.haml
+++ b/app/views/projects/wikis/history.html.haml
@@ -7,28 +7,29 @@
%span.light History for
= link_to @page.title, namespace_project_wiki_path(@project.namespace, @project, @page)
-%table.table
- %thead
- %tr
- %th Page version
- %th Author
- %th Commit Message
- %th Last updated
- %th Format
- %tbody
- - @page.versions.each_with_index do |version, index|
- - commit = version
+.table-holder
+ %table.table
+ %thead
%tr
- %td
- = link_to project_wiki_path_with_version(@project, @page,
- commit.id, index == 0) do
- = truncate_sha(commit.id)
- %td
- = commit.author.name
- %td
- = commit.message
- %td
- #{time_ago_with_tooltip(version.authored_date)}
- %td
- %strong
- = @page.page.wiki.page(@page.page.name, commit.id).try(:format)
+ %th Page version
+ %th Author
+ %th Commit Message
+ %th Last updated
+ %th Format
+ %tbody
+ - @page.versions.each_with_index do |version, index|
+ - commit = version
+ %tr
+ %td
+ = link_to project_wiki_path_with_version(@project, @page,
+ commit.id, index == 0) do
+ = truncate_sha(commit.id)
+ %td
+ = commit.author.name
+ %td
+ = commit.message
+ %td
+ #{time_ago_with_tooltip(version.authored_date)}
+ %td
+ %strong
+ = @page.page.wiki.page(@page.page.name, commit.id).try(:format)
diff --git a/app/views/search/_category.html.haml b/app/views/search/_category.html.haml
index d637abfa76b..481451edb23 100644
--- a/app/views/search/_category.html.haml
+++ b/app/views/search/_category.html.haml
@@ -42,6 +42,13 @@
Wiki
%span.badge
= @search_results.wiki_blobs_count
+ %li{class: ("active" if @scope == 'commits')}
+ = link_to search_filter_path(scope: 'commits') do
+ = icon('history fw')
+ %span
+ Commits
+ %span.badge
+ = @search_results.commits_count
- elsif @show_snippets
%li{class: ("active" if @scope == 'snippet_blobs')}
diff --git a/app/views/search/results/_commit.html.haml b/app/views/search/results/_commit.html.haml
new file mode 100644
index 00000000000..4e6c3965dc6
--- /dev/null
+++ b/app/views/search/results/_commit.html.haml
@@ -0,0 +1,2 @@
+.search-result-row
+ = render 'projects/commits/commit', project: @project, commit: commit
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index b23b2f0d5eb..2e4aab36301 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -6,7 +6,7 @@
type: 'button', |
class: "btn #{ 'active' if default_clone_protocol == 'ssh' }#{ ' has_tooltip' if current_user && current_user.require_ssh_key? }", |
:"data-clone" => project.ssh_url_to_repo, |
- :"data-title" => "Add an SSH key to your profile<br> to pull or push via SSH",
+ :"data-title" => "Add an SSH key to your profile<br> to pull or push via SSH.",
:"data-html" => "true",
:"data-container" => "body"}
SSH
@@ -15,7 +15,7 @@
type: 'button', |
class: "btn #{ 'active' if default_clone_protocol == 'http' }#{ ' has_tooltip' if current_user && current_user.require_password? }", |
:"data-clone" => project.http_url_to_repo, |
- :"data-title" => "Set a password on your account<br> to pull or push via #{gitlab_config.protocol.upcase}",
+ :"data-title" => "Set a password on your account<br> to pull or push via #{gitlab_config.protocol.upcase}.",
:"data-html" => "true",
:"data-container" => "body"}
= gitlab_config.protocol.upcase
diff --git a/app/views/shared/_logo.svg b/app/views/shared/_logo.svg
new file mode 100644
index 00000000000..da49c48acd3
--- /dev/null
+++ b/app/views/shared/_logo.svg
@@ -0,0 +1,21 @@
+<svg width="36px" height="36px" viewBox="0 0 210 210" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="tanuki-logo">
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
+ <g id="logo" sketch:type="MSLayerGroup" transform="translate(0.000000, 10.000000)">
+ <g id="Page-1" sketch:type="MSShapeGroup">
+ <g id="Fill-1-+-Group-24">
+ <g id="Group-24">
+ <g id="Group">
+ <path d="M105.0614,193.655 L105.0614,193.655 L143.7014,74.734 L66.4214,74.734 L105.0614,193.655 L105.0614,193.655 Z" id="Fill-4" fill="#E24329" class="tanuki-shape"></path>
+ <path d="M105.0614,193.6548 L66.4214,74.7338 L12.2684,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-8" fill="#FC6D26" class="tanuki-shape"></path>
+ <path d="M12.2685,74.7341 L12.2685,74.7341 L0.5265,110.8731 C-0.5445,114.1691 0.6285,117.7801 3.4325,119.8171 L105.0615,193.6551 L12.2685,74.7341 L12.2685,74.7341 Z" id="Fill-12" fill="#FCA326" class="tanuki-shape"></path>
+ <path d="M12.2685,74.7342 L66.4215,74.7342 L43.1485,3.1092 C41.9515,-0.5768 36.7375,-0.5758 35.5405,3.1092 L12.2685,74.7342 L12.2685,74.7342 Z" id="Fill-16" fill="#E24329" class="tanuki-shape"></path>
+ <path d="M105.0614,193.6548 L143.7014,74.7338 L197.8544,74.7338 L105.0614,193.6548 L105.0614,193.6548 Z" id="Fill-18" fill="#FC6D26" class="tanuki-shape"></path>
+ <path d="M197.8544,74.7341 L197.8544,74.7341 L209.5964,110.8731 C210.6674,114.1691 209.4944,117.7801 206.6904,119.8171 L105.0614,193.6551 L197.8544,74.7341 L197.8544,74.7341 Z" id="Fill-20" fill="#FCA326" class="tanuki-shape"></path>
+ <path d="M197.8544,74.7342 L143.7014,74.7342 L166.9744,3.1092 C168.1714,-0.5768 173.3854,-0.5758 174.5824,3.1092 L197.8544,74.7342 L197.8544,74.7342 Z" id="Fill-22" fill="#E24329" class="tanuki-shape"></path>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/app/views/shared/issuable/_context.html.haml b/app/views/shared/issuable/_context.html.haml
index cba18c14568..be66256c7b0 100644
--- a/app/views/shared/issuable/_context.html.haml
+++ b/app/views/shared/issuable/_context.html.haml
@@ -45,6 +45,6 @@
.description-block.subscribed{class: ( 'hidden' unless subscribed )}
You're receiving notifications because you're subscribed to this thread.
-:coffeescript
- new Subscription("#{toggle_subscription_path(issuable)}")
- new IssuableContext()
+:javascript
+ new Subscription("#{toggle_subscription_path(issuable)}");
+ new IssuableContext();
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
index 8f16773077e..d1231438ee4 100644
--- a/app/views/shared/issuable/_filter.html.haml
+++ b/app/views/shared/issuable/_filter.html.haml
@@ -42,11 +42,10 @@
class: 'select2 trigger-submit', include_blank: true,
data: {placeholder: 'Milestone'})
- - if @project
- .filter-item.inline.labels-filter
- = select_tag('label_name', project_labels_options(@project),
- class: 'select2 trigger-submit', include_blank: true,
- data: {placeholder: 'Label'})
+ .filter-item.inline.labels-filter
+ = select_tag('label_name', projects_labels_options,
+ class: 'select2 trigger-submit', include_blank: true,
+ data: {placeholder: 'Label'})
.pull-right
= render 'shared/sort_dropdown'
@@ -61,9 +60,9 @@
= hidden_field_tag :state_event, params[:state_event]
= button_tag "Update issues", class: "btn update_selected_issues btn-save"
-:coffeescript
- new UsersSelect()
-
- $('form.filter-form').on 'submit', (event) ->
- event.preventDefault()
- Turbolinks.visit @.action + '&' + $(@).serialize()
+:javascript
+ new UsersSelect();
+ $('form.filter-form').on('submit', function (event) {
+ event.preventDefault();
+ Turbolinks.visit(this.action + '&' + $(this).serialize());
+ });
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 594e54f404c..0fc74d7d2b1 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -27,14 +27,7 @@
= render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do
= render 'projects/zen', f: f, attr: :description,
classes: 'description form-control js-quick-submit'
- .col-sm-12.hint
- .pull-left
- Parsed with
- #{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'), target: '_blank'}.
- .pull-right
- Attach files by dragging &amp; dropping
- or #{link_to 'selecting them', '#', class: 'markdown-selector' }.
-
+ = render 'projects/notes/hints'
.clearfix
.error-alert
%hr
diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml
index 357cfd6a370..e5ffe1e29ae 100644
--- a/app/views/shared/projects/_list.html.haml
+++ b/app/views/shared/projects/_list.html.haml
@@ -17,5 +17,5 @@
= link_to '#', class: 'js-expand' do
Show all
-:coffeescript
- new ProjectsList()
+:javascript
+ new ProjectsList();
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index aee839b44e7..c36995b94d7 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -21,9 +21,7 @@
.project-controls
- if ci && !project.empty_repo? && project.commit
- if ci_commit = project.ci_commit(project.commit.sha)
- = link_to ci_status_path(ci_commit), class: "c#{ci_status_color(ci_commit)}",
- title: "Build status: #{ci_commit.status}", data: {toggle: 'tooltip', placement: 'left'} do
- = ci_status_icon(ci_commit)
+ = render_ci_status(ci_commit)
&nbsp;
- if stars
%span
diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml
new file mode 100644
index 00000000000..0a4a790ec5e
--- /dev/null
+++ b/app/views/shared/snippets/_header.html.haml
@@ -0,0 +1,24 @@
+.snippet-details
+ .page-title
+ .snippet-box{class: visibility_level_color(@snippet.visibility_level)}
+ = visibility_level_icon(@snippet.visibility_level)
+ = visibility_level_label(@snippet.visibility_level)
+ %span.snippet-id Snippet ##{@snippet.id}
+ %span.creator
+ &middot; created by #{link_to_member(@project, @snippet.author, size: 24)}
+ &middot;
+ = time_ago_with_tooltip(@snippet.created_at, placement: 'bottom', html_class: 'snippet_updated_ago')
+ - if @snippet.updated_at != @snippet.created_at
+ %span
+ &middot;
+ = icon('edit', title: 'edited')
+ = time_ago_with_tooltip(@snippet.updated_at, placement: 'bottom', html_class: 'snippet_edited_ago')
+
+ .pull-right
+ - if @snippet.project_id?
+ = render "projects/snippets/actions"
+ - else
+ = render "snippets/actions"
+ .gray-content-block.middle-block
+ %h2.snippet-title
+ = gfm escape_once(@snippet.title)
diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml
index 69a713ad9aa..c6294caddc7 100644
--- a/app/views/shared/snippets/_snippet.html.haml
+++ b/app/views/shared/snippets/_snippet.html.haml
@@ -18,4 +18,3 @@
= image_tag avatar_icon(snippet.author_email), class: "avatar s24", alt: ''
= snippet.author_name
authored #{time_ago_with_tooltip(snippet.created_at)}
-
diff --git a/app/views/sherlock/file_samples/show.html.haml b/app/views/sherlock/file_samples/show.html.haml
new file mode 100644
index 00000000000..cfd11e45b6a
--- /dev/null
+++ b/app/views/sherlock/file_samples/show.html.haml
@@ -0,0 +1,55 @@
+- page_title t('sherlock.title'), t('sherlock.transaction'),
+ t('sherlock.file_sample')
+
+- header_title t('sherlock.title'), sherlock_transactions_path
+
+.gray-content-block
+ .pull-right
+ = link_to(sherlock_transaction_path(@transaction), class: 'btn') do
+ %i.fa.fa-arrow-left
+ = t('sherlock.transaction')
+ .oneline
+ = t('sherlock.file_sample')
+ = @file_sample.id
+
+.prepend-top-default
+ %p
+ %span.light
+ #{t('sherlock.time')}:
+ %strong
+ = @file_sample.duration.round(2)
+ = t('sherlock.milliseconds')
+ %p
+ %span.light
+ #{t('sherlock.events')}:
+ %strong
+ = @file_sample.events
+
+%article.file-holder
+ .file-title
+ %i.fa.fa-file-text-o.fa-fw
+ %strong
+ = @file_sample.file
+ .code.file-content.js-syntax-highlight
+ .line-numbers
+ %table.sherlock-line-samples-table
+ %thead
+ %tr
+ %th= t('sherlock.line_capitalized')
+ %th= t('sherlock.events')
+ %th= t('sherlock.time')
+ %th= t('sherlock.percent')
+ %tbody
+ - @file_sample.line_samples.each_with_index do |sample, index|
+ %tr{class: sample.majority_of?(@file_sample.duration) ? 'slow' : ''}
+ %td= index + 1
+ %td= sample.events
+ %td
+ = sample.duration.round(2)
+ = t('sherlock.milliseconds')
+ %td
+ = sample.percentage_of(@file_sample.duration).round
+ = t('sherlock.percent')
+
+ .sherlock-file-sample
+ = highlight(@file_sample.file, @file_sample.source)
diff --git a/app/views/sherlock/queries/_backtrace.html.haml b/app/views/sherlock/queries/_backtrace.html.haml
new file mode 100644
index 00000000000..5c9294c0ab5
--- /dev/null
+++ b/app/views/sherlock/queries/_backtrace.html.haml
@@ -0,0 +1,27 @@
+.prepend-top-default
+ .panel.panel-default
+ .panel-heading
+ %strong
+ = t('sherlock.application_backtrace')
+ %ul.well-list
+ - @query.application_backtrace.each do |location|
+ %li
+ = location.path
+ %small.light
+ = t('sherlock.line')
+ = location.line
+
+ .panel.panel-default
+ .panel-heading
+ %strong
+ = t('sherlock.full_backtrace')
+ %ul.well-list
+ - @query.backtrace.each do |location|
+ %li
+ - if location.application?
+ %strong= location.path
+ - else
+ = location.path
+ %small.light
+ = t('sherlock.line')
+ = location.line
diff --git a/app/views/sherlock/queries/_general.html.haml b/app/views/sherlock/queries/_general.html.haml
new file mode 100644
index 00000000000..549b47430e6
--- /dev/null
+++ b/app/views/sherlock/queries/_general.html.haml
@@ -0,0 +1,50 @@
+.prepend-top-default
+ .panel.panel-default
+ .panel-heading
+ %strong
+ = t('sherlock.general')
+ %ul.well-list
+ %li
+ %span.light
+ #{t('sherlock.time')}:
+ %strong
+ = @query.duration.round(4)
+ = t('sherlock.milliseconds')
+ %li
+ %span.light
+ #{t('sherlock.origin')}:
+ %strong
+ = @query.last_application_frame.path
+ %small.light
+ = t('sherlock.line')
+ = @query.last_application_frame.line
+
+ .panel.panel-default
+ .panel-heading
+ .pull-right
+ %button.js-clipboard-trigger.btn.btn-xs{title: t('sherlock.copy_to_clipboard'), type: :button}
+ %i.fa.fa-clipboard
+ %pre.hidden
+ = @query.formatted_query
+ %strong
+ = t('sherlock.query')
+ %ul.well-list
+ %li
+ .code.js-syntax-highlight.sherlock-code
+ :preserve
+ #{highlight("#{@query.id}.sql", @query.formatted_query)}
+
+ .panel.panel-default
+ .panel-heading
+ .pull-right
+ %button.js-clipboard-trigger.btn.btn-xs{title: t('sherlock.copy_to_clipboard'), type: :button}
+ %i.fa.fa-clipboard
+ %pre.hidden
+ = @query.explain
+ %strong
+ = t('sherlock.query_plan')
+ %ul.well-list
+ %li
+ .code.js-syntax-highlight.sherlock-code
+ %pre
+ %code= @query.explain
diff --git a/app/views/sherlock/queries/show.html.haml b/app/views/sherlock/queries/show.html.haml
new file mode 100644
index 00000000000..4a84348ac82
--- /dev/null
+++ b/app/views/sherlock/queries/show.html.haml
@@ -0,0 +1,26 @@
+- page_title t('sherlock.title'), t('sherlock.transaction'), t('sherlock.query')
+- header_title t('sherlock.title'), sherlock_transactions_path
+
+%ul.center-top-menu
+ %li.active
+ %a(href="#tab-general" data-toggle="tab")
+ = t('sherlock.general')
+ %li
+ %a(href="#tab-backtrace" data-toggle="tab")
+ = t('sherlock.backtrace')
+
+.gray-content-block
+ .pull-right
+ = link_to(sherlock_transaction_path(@transaction), class: 'btn') do
+ %i.fa.fa-arrow-left
+ = t('sherlock.transaction')
+ .oneline
+ = t('sherlock.query')
+ = @query.id
+
+.tab-content
+ .tab-pane.active#tab-general
+ = render(partial: 'general')
+
+ .tab-pane#tab-backtrace
+ = render(partial: 'backtrace')
diff --git a/app/views/sherlock/transactions/_file_samples.html.haml b/app/views/sherlock/transactions/_file_samples.html.haml
new file mode 100644
index 00000000000..4349c9b7ace
--- /dev/null
+++ b/app/views/sherlock/transactions/_file_samples.html.haml
@@ -0,0 +1,24 @@
+- if @transaction.file_samples.empty?
+ .nothing-here-block
+ = t('sherlock.no_file_samples')
+- else
+ .table-holder
+ %table.table
+ %thead
+ %tr
+ %th= t('sherlock.time_inclusive')
+ %th= t('sherlock.count')
+ %th= t('sherlock.path')
+ %th
+ %tbody
+ - @transaction.sorted_file_samples.each do |sample|
+ %tr
+ %td
+ = sample.duration.round(2)
+ = t('sherlock.milliseconds')
+ %td= @transaction.view_counts.fetch(sample.file, 1)
+ %td= sample.relative_path
+ %td
+ = link_to(t('sherlock.view'),
+ sherlock_transaction_file_sample_path(@transaction, sample),
+ class: 'btn btn-xs')
diff --git a/app/views/sherlock/transactions/_general.html.haml b/app/views/sherlock/transactions/_general.html.haml
new file mode 100644
index 00000000000..4287a0c3203
--- /dev/null
+++ b/app/views/sherlock/transactions/_general.html.haml
@@ -0,0 +1,33 @@
+.prepend-top-default
+ .panel.panel-default
+ .panel-heading
+ %strong
+ = t('sherlock.general')
+ %ul.well-list
+ %li
+ %span.light
+ #{t('sherlock.id')}:
+ %strong
+ = @transaction.id
+ %li
+ %span.light
+ #{t('sherlock.type')}:
+ %strong
+ = @transaction.type
+ %li
+ %span.light
+ #{t('sherlock.path')}:
+ %strong
+ = @transaction.path
+ %li
+ %span.light
+ #{t('sherlock.time')}:
+ %strong
+ = @transaction.duration.round(2)
+ = t('sherlock.seconds')
+ %li
+ %span.light
+ #{t('sherlock.finished_at')}:
+ %strong
+ = time_ago_in_words(@transaction.finished_at)
+ = t('sherlock.ago')
diff --git a/app/views/sherlock/transactions/_queries.html.haml b/app/views/sherlock/transactions/_queries.html.haml
new file mode 100644
index 00000000000..b7e0162e80d
--- /dev/null
+++ b/app/views/sherlock/transactions/_queries.html.haml
@@ -0,0 +1,24 @@
+- if @transaction.queries.empty?
+ .nothing-here-block
+ = t('sherlock.no_queries')
+- else
+ .table-holder
+ %table.table#sherlock-queries
+ %thead
+ %tr
+ %th= t('sherlock.time')
+ %th= t('sherlock.query')
+ %td
+ %tbody
+ - @transaction.sorted_queries.each do |query|
+ %tr
+ %td
+ = query.duration.round(2)
+ = t('sherlock.milliseconds')
+ %td
+ .code.js-syntax-highlight.sherlock-code
+ = highlight("#{query.id}.sql", query.formatted_query)
+ %td
+ = link_to(t('sherlock.view'),
+ sherlock_transaction_query_path(@transaction, query),
+ class: 'btn btn-xs')
diff --git a/app/views/sherlock/transactions/index.html.haml b/app/views/sherlock/transactions/index.html.haml
new file mode 100644
index 00000000000..010e1a2a902
--- /dev/null
+++ b/app/views/sherlock/transactions/index.html.haml
@@ -0,0 +1,42 @@
+- page_title t('sherlock.title')
+- header_title t('sherlock.title'), sherlock_transactions_path
+
+.gray-content-block
+ .pull-right
+ = link_to(destroy_all_sherlock_transactions_path,
+ class: 'btn btn-danger',
+ method: :delete) do
+ %i.fa.fa-trash
+ = t('sherlock.delete_all_transactions')
+ .oneline= t('sherlock.introduction')
+
+- if @transactions.empty?
+ .nothing-here-block= t('sherlock.no_transactions')
+- else
+ .table-holder
+ %table.table
+ %thead
+ %tr
+ %th= t('sherlock.type')
+ %th= t('sherlock.path')
+ %th= t('sherlock.time')
+ %th= t('sherlock.queries')
+ %th= t('sherlock.finished_at')
+ %th
+ %tbody
+ - @transactions.each do |trans|
+ %tr
+ %td= trans.type
+ %td
+ %span{title: trans.path}
+ = truncate(trans.path, length: 70)
+ %td
+ = trans.duration.round(2)
+ = t('sherlock.seconds')
+ %td= trans.queries.length
+ %td
+ = time_ago_in_words(trans.finished_at)
+ = t('sherlock.ago')
+ %td
+ = link_to(sherlock_transaction_path(trans), class: 'btn btn-xs') do
+ = t('sherlock.view')
diff --git a/app/views/sherlock/transactions/show.html.haml b/app/views/sherlock/transactions/show.html.haml
new file mode 100644
index 00000000000..3c8ffb06648
--- /dev/null
+++ b/app/views/sherlock/transactions/show.html.haml
@@ -0,0 +1,36 @@
+- page_title t('sherlock.title'), t('sherlock.transaction')
+- header_title t('sherlock.title'), sherlock_transactions_path
+
+%ul.center-top-menu
+ %li.active
+ %a(href="#tab-general" data-toggle="tab")
+ = t('sherlock.general')
+ %li
+ %a(href="#tab-queries" data-toggle="tab")
+ = t('sherlock.queries')
+ %span.badge
+ #{@transaction.queries.length}
+ %li
+ %a(href="#tab-file-samples" data-toggle="tab")
+ = t('sherlock.file_samples')
+ %span.badge
+ #{@transaction.file_samples.length}
+
+.gray-content-block
+ .pull-right
+ = link_to(sherlock_transactions_path, class: 'btn') do
+ %i.fa.fa-arrow-left
+ = t('sherlock.all_transactions')
+ .oneline
+ = t('sherlock.transaction')
+ = @transaction.id
+
+.tab-content
+ .tab-pane.active#tab-general
+ = render(partial: 'general')
+
+ .tab-pane#tab-queries
+ = render(partial: 'queries')
+
+ .tab-pane#tab-file-samples
+ = render(partial: 'file_samples')
diff --git a/app/views/snippets/_actions.html.haml b/app/views/snippets/_actions.html.haml
new file mode 100644
index 00000000000..1979ae6d5bc
--- /dev/null
+++ b/app/views/snippets/_actions.html.haml
@@ -0,0 +1,11 @@
+= link_to new_snippet_path, class: 'btn btn-grouped new-snippet-link', title: "New Snippet" do
+ = icon('plus')
+ New Snippet
+- if can?(current_user, :update_personal_snippet, @snippet)
+ = link_to edit_snippet_path(@snippet), class: "btn btn-grouped snippable-edit" do
+ = icon('pencil-square-o')
+ Edit
+- if can?(current_user, :admin_personal_snippet, @snippet)
+ = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-remove", title: 'Delete Snippet' do
+ = icon('trash-o')
+ Delete
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 97374e073dc..69d8899d4c1 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -1,41 +1,14 @@
- page_title @snippet.title, "Snippets"
-%h4.page-title
- = @snippet.title
- - if @snippet.private?
- %span.label.label-success
- %i.fa.fa-lock
- private
-
- .pull-right
- = link_to new_snippet_path, class: "btn btn-new btn-sm", title: "New Snippet" do
- Add new snippet
-
-.append-bottom-10.prepend-top-10
- .pull-right
- %span.light
- created by
- = link_to user_snippets_path(@snippet.author) do
- = @snippet.author_name
-
- .back-link
- - if @snippet.author == current_user
- = link_to dashboard_snippets_path do
- &larr; your snippets
- - else
- = link_to explore_snippets_path do
- &larr; explore snippets
-
-.file-holder
- .file-title
- %i.fa.fa-file
- %strong
- = @snippet.file_name
- .file-actions
- .btn-group
- - if can?(current_user, :update_personal_snippet, @snippet)
- = link_to "edit", edit_snippet_path(@snippet), class: "btn btn-sm", title: 'Edit Snippet'
- = link_to "raw", raw_snippet_path(@snippet), class: "btn btn-sm", target: "_blank"
- - if can?(current_user, :admin_personal_snippet, @snippet)
- = link_to "remove", snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-sm btn-remove", title: 'Delete Snippet'
- = render 'shared/snippets/blob'
+.snippet-holder
+ = render 'shared/snippets/header'
+
+ %article.file-holder
+ .file-title
+ = blob_icon 0, @snippet.file_name
+ %strong
+ = @snippet.file_name
+ .file-actions.hidden-xs
+ .btn-group.tree-btn-group
+ = link_to 'Raw', raw_snippet_path(@snippet), class: "btn btn-sm", target: "_blank"
+ = render 'shared/snippets/blob'
diff --git a/app/views/users/_projects.html.haml b/app/views/users/_projects.html.haml
deleted file mode 100644
index a126a858ea8..00000000000
--- a/app/views/users/_projects.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-- if local_assigns.has_key?(:contributed_projects) && contributed_projects.present?
- .panel.panel-default.contributed-projects
- .panel-heading Projects contributed to
- = render 'shared/projects/list',
- projects: contributed_projects.sort_by(&:star_count).reverse,
- projects_limit: 5, stars: true, avatar: false
-
-- if local_assigns.has_key?(:projects) && projects.present?
- .panel.panel-default
- .panel-heading Personal projects
- = render 'shared/projects/list',
- projects: projects.sort_by(&:star_count).reverse,
- projects_limit: 10, stars: true, avatar: false
diff --git a/app/views/users/calendar.html.haml b/app/views/users/calendar.html.haml
index 922b0c6cebf..7f29918dba3 100644
--- a/app/views/users/calendar.html.haml
+++ b/app/views/users/calendar.html.haml
@@ -1,7 +1,3 @@
-%h4
- Contributions calendar
- .pull-right
- %small Issues, merge requests and push events
#cal-heatmap.calendar
:javascript
new Calendar(
@@ -10,3 +6,5 @@
#{@starting_month},
'#{user_calendar_activities_path}'
);
+
+.calendar-hint Summary of issues, merge requests and push events
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 2a64708d07c..d5a92cb816a 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -6,61 +6,114 @@
= render 'shared/show_aside'
-.row
- %section.col-md-7
- .header-with-avatar
- = link_to avatar_icon(@user, 400), target: '_blank' do
- = image_tag avatar_icon(@user, 90), class: "avatar avatar-tile s90", alt: ''
- %h3
- = @user.name
- - if @user == current_user
- .pull-right.hidden-xs
- = link_to profile_path, class: 'btn btn-sm' do
- = icon('user')
- Profile settings
- - elsif current_user
- .report_abuse.pull-right
- - if @user.abuse_report
- %span#report_abuse_btn.light.btn.btn-sm.btn-close{title: 'Already reported for abuse', data: {toggle: 'tooltip', placement: 'right', container: 'body'}}
- = icon('exclamation-circle')
- - else
- %a.light.btn.btn-sm{href: new_abuse_report_path(user_id: @user.id), title: 'Report abuse', data: {toggle: 'tooltip', placement: 'right', container: 'body'}}
- = icon('exclamation-circle')
+.cover-block
+ .avatar-holder
+ = link_to avatar_icon(@user, 400), target: '_blank' do
+ = image_tag avatar_icon(@user, 90), class: "avatar s90", alt: ''
+ .cover-title
+ = @user.name
- .username
- @#{@user.username}
- .description
- - if @user.bio.present?
- = @user.bio
+ .cover-desc
+ %span
+ @#{@user.username}.
+ - if @user.bio.present?
+ %span
+ #{@user.bio}.
+ %span
+ Member since #{@user.created_at.stamp("Aug 21, 2011")}
- .clearfix
+ .cover-desc
+ - unless @user.public_email.blank?
+ .profile-link-holder
+ = link_to @user.public_email, "mailto:#{@user.public_email}"
+ - unless @user.skype.blank?
+ .profile-link-holder
+ = link_to "skype:#{@user.skype}", title: "Skype" do
+ = icon('skype')
+ - unless @user.linkedin.blank?
+ .profile-link-holder
+ = link_to "https://www.linkedin.com/in/#{@user.linkedin}", title: "LinkedIn" do
+ = icon('linkedin-square')
+ - unless @user.twitter.blank?
+ .profile-link-holder
+ = link_to "https://twitter.com/#{@user.twitter}", title: "Twitter" do
+ = icon('twitter-square')
+ - unless @user.website_url.blank?
+ .profile-link-holder
+ = link_to @user.short_website_url, @user.full_website_url
+ - unless @user.location.blank?
+ .profile-link-holder
+ = icon('map-marker')
+ = @user.location
- - if @groups.any?
- .prepend-top-20
- %h4 Groups
- = render 'groups', groups: @groups
- %hr
- .hidden-xs
- .user-calendar
- %h4.center.light
- %i.fa.fa-spinner.fa-spin
- .user-calendar-activities
- %hr
- %h4
- User Activity
+ .cover-controls
+ - if @user == current_user
+ = link_to profile_path, class: 'btn btn-gray' do
+ = icon('pencil')
+ - elsif current_user
+ %span.report-abuse
+ - if @user.abuse_report
+ %button.btn.btn-danger{ title: 'Already reported for abuse',
+ data: { toggle: 'tooltip', placement: 'left', container: 'body' }}
+ = icon('exclamation-circle')
+ - else
+ = link_to new_abuse_report_path(user_id: @user.id), class: 'btn btn-gray',
+ title: 'Report abuse', data: {toggle: 'tooltip', placement: 'left', container: 'body'} do
+ = icon('exclamation-circle')
+ - if current_user
+ &nbsp;
+ = link_to user_path(@user, :atom, { private_token: current_user.private_token }), class: 'btn btn-gray' do
+ = icon('rss')
- - if current_user
- %span.rss-icon.pull-right
- = link_to user_path(@user, :atom, { private_token: current_user.private_token }) do
- %strong
- %i.fa.fa-rss
+.gray-content-block.second-block
+ .user-calendar
+ %h4.center.light
+ %i.fa.fa-spinner.fa-spin
+ .user-calendar-activities
+
+%ul.center-middle-menu
+ %li.active
+ = link_to "#activity", 'data-toggle' => 'tab' do
+ Activity
+ - if @groups.any?
+ %li
+ = link_to "#groups", 'data-toggle' => 'tab' do
+ Groups
+ - if @contributed_projects.present?
+ %li
+ = link_to "#contributed", 'data-toggle' => 'tab' do
+ Contributed projects
+ - if @projects.present?
+ %li
+ = link_to "#personal", 'data-toggle' => 'tab' do
+ Personal projects
+
+.tab-content
+ .tab-pane.active#activity
.content_list
= spinner
- %aside.col-md-5
- = render 'profile', user: @user
- = render 'projects', projects: @projects, contributed_projects: @contributed_projects
-:coffeescript
- $(".user-calendar").load("#{user_calendar_path}")
+ - if @groups.any?
+ .tab-pane#groups
+ %ul.content-list
+ - @groups.each do |group|
+ = render 'shared/groups/group', group: group
+
+ - if @contributed_projects.present?
+ .tab-pane#contributed
+ .contributed-projects
+ = render 'shared/projects/list',
+ projects: @contributed_projects.sort_by(&:star_count).reverse,
+ projects_limit: 5, stars: true, avatar: true
+
+ - if @projects.present?
+ .tab-pane#personal
+ .personal-projects
+ = render 'shared/projects/list',
+ projects: @projects.sort_by(&:star_count).reverse,
+ projects_limit: 10, stars: true, avatar: true
+
+:javascript
+ $(".user-calendar").load("#{user_calendar_path}");
diff --git a/app/workers/repository_archive_cache_worker.rb b/app/workers/repository_archive_cache_worker.rb
new file mode 100644
index 00000000000..47c5a670ed4
--- /dev/null
+++ b/app/workers/repository_archive_cache_worker.rb
@@ -0,0 +1,9 @@
+class RepositoryArchiveCacheWorker
+ include Sidekiq::Worker
+
+ sidekiq_options queue: :default
+
+ def perform
+ Repository.clean_old_archives
+ end
+end
diff --git a/app/workers/repository_archive_worker.rb b/app/workers/repository_archive_worker.rb
deleted file mode 100644
index 021c1139568..00000000000
--- a/app/workers/repository_archive_worker.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-class RepositoryArchiveWorker
- include Sidekiq::Worker
-
- sidekiq_options queue: :archive_repo
-
- attr_accessor :project, :ref, :format
-
- def perform(project_id, ref, format)
- @project = Project.find(project_id)
- @ref, @format = ref, format.downcase
-
- repository = project.repository
-
- repository.clean_old_archives
-
- return unless file_path
- return if archived? || archiving?
-
- repository.archive_repo(ref, storage_path, format)
- end
-
- private
-
- def storage_path
- Gitlab.config.gitlab.repository_downloads_path
- end
-
- def file_path
- @file_path ||= project.repository.archive_file_path(ref, storage_path, format)
- end
-
- def pid_file_path
- @pid_file_path ||= project.repository.archive_pid_file_path(ref, storage_path, format)
- end
-
- def archived?
- File.exist?(file_path)
- end
-
- def archiving?
- File.exist?(pid_file_path)
- end
-end
diff --git a/app/workers/stuck_ci_builds_worker.rb b/app/workers/stuck_ci_builds_worker.rb
new file mode 100644
index 00000000000..ad02a3b16d9
--- /dev/null
+++ b/app/workers/stuck_ci_builds_worker.rb
@@ -0,0 +1,18 @@
+class StuckCiBuildsWorker
+ include Sidekiq::Worker
+ include Sidetiq::Schedulable
+
+ BUILD_STUCK_TIMEOUT = 1.day
+
+ recurrence { daily }
+
+ def perform
+ Rails.logger.info 'Cleaning stuck builds'
+
+ builds = Ci::Build.running_or_pending.where('updated_at < ?', BUILD_STUCK_TIMEOUT.ago)
+ builds.find_each(batch_size: 50).each do |build|
+ Rails.logger.debug "Dropping stuck #{build.status} build #{build.id} for runner #{build.runner_id}"
+ build.drop
+ end
+ end
+end