diff --git a/.gitignore b/.gitignore index 7a7b5c9393626f3d0cbc63b0d25ca84ec7a9feae..3e30fb8cf77f62ecf6c9862c501a7566aabb71a7 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,6 @@ public/assets/ public/uploads.* public/uploads/ rails_best_practices_output.html -tags +/tags tmp/ vendor/bundle/* diff --git a/CHANGELOG b/CHANGELOG index 3af83ddc25664d58fdca2675c08d1788e980cf27..be0c005fa061cd2cace7ff310477e77934bbd846 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,7 +1,9 @@ Please view this file on the master branch, on stable branches it's out of date. v 7.11.0 (unreleased) + - Make Reply-To config apply to change e-mail confirmation and other Devise notifications (Stan Hu) - Don't allow a merge request to be merged when its title starts with "WIP". + - Add a page title to every page. - Get Gitorious importer to work again. - Fix clone URL field and X11 Primary selection (Dmitry Medvinsky) - Ignore invalid lines in .gitmodules @@ -11,6 +13,7 @@ v 7.11.0 (unreleased) - Fix "Revspec not found" errors when viewing diffs in a forked project with submodules (Stan Hu) - - Fix broken file browsing with relative submodule in personal projects (Stan Hu) + - Fix DB error when trying to tag a repository (Stan Hu) - Add "Reply quoting selected text" shortcut key (`r`) - Fix bug causing `@whatever` inside an issue's first code block to be picked up as a user mention. - Fix bug causing `@whatever` inside an inline code snippet (backtick-style) to be picked up as a user mention. @@ -21,7 +24,7 @@ v 7.11.0 (unreleased) - Include commit comments in MR from a forked project. - Fix adding new group members from admin area - Add default project and snippet visibility settings to the admin web UI. - - + - Show incompatible projects in Google Code import status (Stan Hu) - Fix bug where commit data would not appear in some subdirectories (Stan Hu) - Fix bug where Slack service channel was not saved in admin template settings. (Stan Hu) - Move snippets UI to fluid layout diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 9aee3b281f3f78653653d631902c20292607c766..06787ddf874933700fa646a0d78ea54bb3697354 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -8,7 +8,6 @@ class Dispatcher initPageScripts: -> page = $('body').attr('data-page') - project_id = $('body').attr('data-project-id') unless page return false diff --git a/app/assets/stylesheets/generic/typography.scss b/app/assets/stylesheets/generic/typography.scss index 80190424c1b056de0591b5ac855a78fb94ffbd84..36a9a540747d8aea5f9883ab3a9bb65f66928f8b 100644 --- a/app/assets/stylesheets/generic/typography.scss +++ b/app/assets/stylesheets/generic/typography.scss @@ -35,7 +35,12 @@ pre { /* Link to current header. */ h1, h2, h3, h4, h5, h6 { position: relative; - &:hover > :last-child { + + a.anchor { + display: none; + } + + &:hover > a.anchor { $size: 16px; position: absolute; right: 100%; diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb index fe5456f820caec82e5060fb4e841dade4860e957..56e24386463db3a95e794faf0ed9ed83df635336 100644 --- a/app/controllers/admin/application_controller.rb +++ b/app/controllers/admin/application_controller.rb @@ -2,8 +2,8 @@ # # Automatically sets the layout and ensures an administrator is logged in class Admin::ApplicationController < ApplicationController - layout 'admin' before_action :authenticate_admin! + layout 'admin' def authenticate_admin! return render_404 unless current_user.is_admin? diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 69fd7901832f1f85093e173408b818c34ad176a3..c9b34eac4b081635567be534bb2dbcd38c3f57ad 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,6 +3,7 @@ require 'gon' class ApplicationController < ActionController::Base include Gitlab::CurrentSettings include GitlabRoutingHelper + include PageLayoutHelper PER_PAGE = 20 diff --git a/app/controllers/dashboard/application_controller.rb b/app/controllers/dashboard/application_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..962ea38d6c9c01020e2cc888a1b915261032c5af --- /dev/null +++ b/app/controllers/dashboard/application_controller.rb @@ -0,0 +1,3 @@ +class Dashboard::ApplicationController < ApplicationController + layout 'dashboard' +end diff --git a/app/controllers/dashboard/groups_controller.rb b/app/controllers/dashboard/groups_controller.rb index ed14f4e1f3baa9689c8d000381dc67179560a7f3..3bc94ff218747c10c310952971dd61dbf8be6f99 100644 --- a/app/controllers/dashboard/groups_controller.rb +++ b/app/controllers/dashboard/groups_controller.rb @@ -1,4 +1,4 @@ -class Dashboard::GroupsController < ApplicationController +class Dashboard::GroupsController < Dashboard::ApplicationController def index @group_members = current_user.group_members.page(params[:page]).per(PER_PAGE) end diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb index 33227e7f1d8bc6ec1e8e3d352a5310b685ce4814..53896d4f2c73a356334d9e88b36f96b22c3aa71b 100644 --- a/app/controllers/dashboard/milestones_controller.rb +++ b/app/controllers/dashboard/milestones_controller.rb @@ -1,4 +1,4 @@ -class Dashboard::MilestonesController < ApplicationController +class Dashboard::MilestonesController < Dashboard::ApplicationController before_action :load_projects def index diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb index 426bc6154153053a82ffa0e54a59e1a22c34c3ac..da96171e88568e7c5bb8ce55e3e350763f58c420 100644 --- a/app/controllers/dashboard/projects_controller.rb +++ b/app/controllers/dashboard/projects_controller.rb @@ -1,4 +1,4 @@ -class Dashboard::ProjectsController < ApplicationController +class Dashboard::ProjectsController < Dashboard::ApplicationController before_action :event_filter def starred diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 40b5de1295a0447005f585e5bc19c9d4bbc37f75..17ddde68f93efc0a4db76e8ebc55114d00094de7 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -1,8 +1,8 @@ -class DashboardController < ApplicationController - respond_to :html - +class DashboardController < Dashboard::ApplicationController before_action :load_projects, except: [:projects] before_action :event_filter, only: :show + + respond_to :html def show @projects = @projects.includes(:namespace) diff --git a/app/controllers/explore/application_controller.rb b/app/controllers/explore/application_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..4b275033d26c76158706ff988d8a9aa4bae5fe2b --- /dev/null +++ b/app/controllers/explore/application_controller.rb @@ -0,0 +1,3 @@ +class Explore::ApplicationController < ApplicationController + layout 'explore' +end diff --git a/app/controllers/explore/groups_controller.rb b/app/controllers/explore/groups_controller.rb index a7250b799f352141d412f47efe062dd0d2a4fb6a..55cda0cff17bada4f7cbc701bf1c4b7aba27b971 100644 --- a/app/controllers/explore/groups_controller.rb +++ b/app/controllers/explore/groups_controller.rb @@ -1,9 +1,7 @@ -class Explore::GroupsController < ApplicationController +class Explore::GroupsController < Explore::ApplicationController skip_before_action :authenticate_user!, :reject_blocked, :set_current_user_for_observers - layout "explore" - def index @groups = GroupsFinder.new.execute(current_user) @groups = @groups.search(params[:search]) if params[:search].present? diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb index b1b0a2514dc0858ff30ffcb74dd10ec1e2e6232f..e9bcb44f6b3967489443f96cc477a7560890217f 100644 --- a/app/controllers/explore/projects_controller.rb +++ b/app/controllers/explore/projects_controller.rb @@ -1,9 +1,7 @@ -class Explore::ProjectsController < ApplicationController +class Explore::ProjectsController < Explore::ApplicationController skip_before_action :authenticate_user!, :reject_blocked - layout 'explore' - def index @projects = ProjectsFinder.new.execute(current_user) @tags = @projects.tags_on(:tags) diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index 469a6813ee22a5e80f262705b3ed7208b3964c4c..4df9d1b7533c2d229ca4b50d1b9d06664b57ea01 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -1,4 +1,5 @@ class Groups::ApplicationController < ApplicationController + layout 'group' private @@ -17,12 +18,4 @@ class Groups::ApplicationController < ApplicationController return render_404 end end - - def determine_layout - if current_user - 'group' - else - 'public_group' - end - end end diff --git a/app/controllers/groups/avatars_controller.rb b/app/controllers/groups/avatars_controller.rb index 38071410f404a12b4b40ace7b181f6a5b12bb0fd..6aa64222f7789601cfbfbca55ed02ee5b69d8cb1 100644 --- a/app/controllers/groups/avatars_controller.rb +++ b/app/controllers/groups/avatars_controller.rb @@ -1,6 +1,4 @@ class Groups::AvatarsController < ApplicationController - layout "profile" - def destroy @group = Group.find_by(path: params[:group_id]) @group.remove_avatar! diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb index 5648a652e8e8a5da4e4f0c8891695c0e48e1077a..a11c554a2af43ec2da0ab679a8db8a298c59ffae 100644 --- a/app/controllers/groups/group_members_controller.rb +++ b/app/controllers/groups/group_members_controller.rb @@ -6,8 +6,6 @@ class Groups::GroupMembersController < Groups::ApplicationController before_action :authorize_read_group! before_action :authorize_admin_group!, except: [:index, :leave] - layout :determine_layout - def index @project = @group.projects.find(params[:project_id]) if params[:project_id] @members = @group.group_members diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index 41564b04a92482bd297e042d4e9029daf8aab23a..669f7f3126df188bb34056a3cd7246506e5f9b1a 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -1,6 +1,4 @@ -class Groups::MilestonesController < ApplicationController - layout 'group' - +class Groups::MilestonesController < Groups::ApplicationController before_action :authorize_group_milestone!, only: :update def index diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 294af0b170450ef6a198a0b11e00bf4bd4813aed..34f0b257db3b48efc784c39e0a4b177b3b5c4450 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -11,7 +11,6 @@ class GroupsController < Groups::ApplicationController # Load group projects before_action :load_projects, except: [:new, :create, :projects, :edit, :update] before_action :event_filter, only: :show - before_action :set_title, only: [:new, :create] layout :determine_layout @@ -119,17 +118,11 @@ class GroupsController < Groups::ApplicationController end end - def set_title - @title = 'New Group' - end - def determine_layout if [:new, :create].include?(action_name.to_sym) - 'navless' - elsif current_user - 'group' + 'application' else - 'public_group' + 'group' end end diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb index 35ece5b270b95c119292704452884f888e1ad650..8a45dc8860d15f20b40299edd95e90186fc482f7 100644 --- a/app/controllers/help_controller.rb +++ b/app/controllers/help_controller.rb @@ -1,14 +1,16 @@ class HelpController < ApplicationController + layout 'help' + def index end def show - category = clean_path_info(path_params[:category]) - file = path_params[:file] + @category = clean_path_info(path_params[:category]) + @file = path_params[:file] respond_to do |format| format.any(:markdown, :md, :html) do - path = Rails.root.join('doc', category, "#{file}.md") + path = Rails.root.join('doc', @category, "#{@file}.md") if File.exist?(path) @markdown = File.read(path) @@ -22,7 +24,7 @@ class HelpController < ApplicationController # Allow access to images in the doc folder format.any(:png, :gif, :jpeg) do - path = Rails.root.join('doc', category, "#{file}.#{params[:format]}") + path = Rails.root.join('doc', @category, "#{@file}.#{params[:format]}") if File.exist?(path) send_file(path, disposition: 'inline') diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb index 5adf6ed7853d655e471a590c5a7f394b28d45c30..4aa6d28c9a803a9e875123b3ea3edcc3f1e64e9b 100644 --- a/app/controllers/import/google_code_controller.rb +++ b/app/controllers/import/google_code_controller.rb @@ -72,6 +72,7 @@ class Import::GoogleCodeController < Import::BaseController end @repos = client.repos + @incompatible_repos = client.incompatible_repos @already_added_projects = current_user.created_projects.where(import_type: "google_code") already_added_projects_names = @already_added_projects.pluck(:import_source) diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index a29c03395f42ca43a94cf61d7a473efc32500c87..eb3c82335308692bf86d90b424d7167313d75be2 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -4,8 +4,6 @@ class InvitesController < ApplicationController respond_to :html - layout 'navless' - def show end diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb index ea256de2c3e53ce6f59b4745fb29a906ef27d97f..507b8290a2b079861eb0143719dcbcd683908a3c 100644 --- a/app/controllers/oauth/applications_controller.rb +++ b/app/controllers/oauth/applications_controller.rb @@ -1,6 +1,9 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController + include PageLayoutHelper + before_action :authenticate_user! - layout "profile" + + layout 'profile' def index head :forbidden and return diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb index 6d3c1a320db1d0ca1ee30e86ada197c4c8c89ff9..24025d8c723f27146a4676685071024e19029903 100644 --- a/app/controllers/oauth/authorizations_controller.rb +++ b/app/controllers/oauth/authorizations_controller.rb @@ -1,6 +1,7 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController before_action :authenticate_resource_owner! - layout "profile" + + layout 'profile' def new if pre_auth.authorizable? diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb index 0b27ce7da7291db743126bae189f107e948652d5..3ab6def511c8b3ca54c3d1c70b32c2ad09a89495 100644 --- a/app/controllers/oauth/authorized_applications_controller.rb +++ b/app/controllers/oauth/authorized_applications_controller.rb @@ -1,5 +1,7 @@ class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController - layout "profile" + include PageLayoutHelper + + layout 'profile' def destroy Doorkeeper::AccessToken.revoke_all_for(params[:id], current_resource_owner) diff --git a/app/controllers/profiles/accounts_controller.rb b/app/controllers/profiles/accounts_controller.rb index 9bd34fe22613ea5401ab2408887a3e277414ef47..175afbf84259fa09434ce6da423a14d90d7a9b3f 100644 --- a/app/controllers/profiles/accounts_controller.rb +++ b/app/controllers/profiles/accounts_controller.rb @@ -1,6 +1,4 @@ -class Profiles::AccountsController < ApplicationController - layout "profile" - +class Profiles::AccountsController < Profiles::ApplicationController def show @user = current_user end diff --git a/app/controllers/profiles/application_controller.rb b/app/controllers/profiles/application_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..c8be288b9a077ec86c880496a5640baa82ffb5b5 --- /dev/null +++ b/app/controllers/profiles/application_controller.rb @@ -0,0 +1,3 @@ +class Profiles::ApplicationController < ApplicationController + layout 'profile' +end diff --git a/app/controllers/profiles/avatars_controller.rb b/app/controllers/profiles/avatars_controller.rb index 57f3bbf0627ad4d79fe4e712b2f8504ec5c3cf46..f193adb46b488734c3e7c294823714ac92062f6e 100644 --- a/app/controllers/profiles/avatars_controller.rb +++ b/app/controllers/profiles/avatars_controller.rb @@ -1,6 +1,4 @@ -class Profiles::AvatarsController < ApplicationController - layout "profile" - +class Profiles::AvatarsController < Profiles::ApplicationController def destroy @user = current_user @user.remove_avatar! diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb index 954c98c0d9ff6775ba75fa3d9d9090a2787088de..3e904700de5fb9607660ea952d1e0e4d94b145a4 100644 --- a/app/controllers/profiles/emails_controller.rb +++ b/app/controllers/profiles/emails_controller.rb @@ -1,6 +1,4 @@ -class Profiles::EmailsController < ApplicationController - layout "profile" - +class Profiles::EmailsController < Profiles::ApplicationController def index @primary = current_user.email @public_email = current_user.public_email diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb index b0a5a631c63e3282a4aed088b7ad2749a7ad7581..f3224148fda5b478a9091e3671b45c65dfc6c3e3 100644 --- a/app/controllers/profiles/keys_controller.rb +++ b/app/controllers/profiles/keys_controller.rb @@ -1,5 +1,4 @@ -class Profiles::KeysController < ApplicationController - layout "profile" +class Profiles::KeysController < Profiles::ApplicationController skip_before_action :authenticate_user!, only: [:get_keys] def index diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb index 3fdcbbab61b531633827a36f336393e9d185f137..22423651c1747c9928f32999f009fc78f7c0cf1f 100644 --- a/app/controllers/profiles/notifications_controller.rb +++ b/app/controllers/profiles/notifications_controller.rb @@ -1,6 +1,4 @@ -class Profiles::NotificationsController < ApplicationController - layout 'profile' - +class Profiles::NotificationsController < Profiles::ApplicationController def show @user = current_user @notification = current_user.notification diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb index b719a7fe9a9ca495c522542243ce653fb2056637..c780e0983f93ae07443138cb2a42ef95828a767b 100644 --- a/app/controllers/profiles/passwords_controller.rb +++ b/app/controllers/profiles/passwords_controller.rb @@ -1,12 +1,11 @@ -class Profiles::PasswordsController < ApplicationController - layout :determine_layout - +class Profiles::PasswordsController < Profiles::ApplicationController skip_before_action :check_password_expiration, only: [:new, :create] before_action :set_user - before_action :set_title before_action :authorize_change_password! + layout :determine_layout + def new end @@ -66,13 +65,9 @@ class Profiles::PasswordsController < ApplicationController @user = current_user end - def set_title - @title = "New password" - end - def determine_layout if [:new, :create].include?(action_name.to_sym) - 'navless' + 'application' else 'profile' end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index eb001e8d73955ed5b8028e06e34cc3c5b74b06e5..f4366c18e7be0be077632b107d43154a9d912d94 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -1,12 +1,10 @@ -class ProfilesController < ApplicationController +class ProfilesController < Profiles::ApplicationController include ActionView::Helpers::SanitizeHelper before_action :user before_action :authorize_change_username!, only: :update_username skip_before_action :require_email, only: [:show, :update] - layout 'profile' - def show end diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index f7a28e920d190d139444d713509e04396ff4af85..ee88d49b40036a6fa125e74dcd0dd1a6f3bd048a 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -1,7 +1,7 @@ class Projects::ApplicationController < ApplicationController before_action :project before_action :repository - layout :determine_layout + layout 'project' def authenticate_user! # Restrict access to Projects area only @@ -17,14 +17,6 @@ class Projects::ApplicationController < ApplicationController super end - def determine_layout - if current_user - 'projects' - else - 'public_projects' - end - end - def require_branch_head unless @repository.branch_names.include?(@ref) redirect_to( diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 22a12c4b9ae025e4d4d2f6ebd495e3648095c0f3..9c3763d5934e0245cc7e8133b2e136fdd7510fa1 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -1,6 +1,4 @@ class Projects::AvatarsController < Projects::ApplicationController - layout 'project' - before_action :project def show diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb index 01a079d2e6593d9a3bdb6e05d5d9bd3778d655e7..9e72597ea87f3296183ab325ab22e64637e3de23 100644 --- a/app/controllers/projects/forks_controller.rb +++ b/app/controllers/projects/forks_controller.rb @@ -18,7 +18,6 @@ class Projects::ForksController < Projects::ApplicationController notice: 'Project was successfully forked.' ) else - @title = 'Fork project' render :error end end diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb index e2d0b0d945908c9746c7a94e4de8422b98ea675a..71ecc20dd95ea7fe681e5b9ed5ef378974eeb8e6 100644 --- a/app/controllers/projects/uploads_controller.rb +++ b/app/controllers/projects/uploads_controller.rb @@ -1,6 +1,4 @@ class Projects::UploadsController < Projects::ApplicationController - layout 'project' - skip_before_action :authenticate_user!, :reject_blocked!, :project, :repository, if: -> { action_name == 'show' && image? } diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 883e5865a21060a040d6d8ec5b6e2f7b98ec2293..dc4303515510a7767e8ba219ae7db53eedf88e4f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -6,17 +6,16 @@ class ProjectsController < ApplicationController # Authorize before_action :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive] - before_action :set_title, only: [:new, :create] before_action :event_filter, only: :show - layout 'navless', only: [:new, :create, :fork] + layout :determine_layout def new @project = Project.new end def edit - render 'edit', layout: 'project_settings' + render 'edit' end def create @@ -46,7 +45,7 @@ class ProjectsController < ApplicationController end format.js else - format.html { render 'edit', layout: 'project_settings' } + format.html { render 'edit' } format.js end end @@ -72,13 +71,13 @@ class ProjectsController < ApplicationController format.html do if @project.repository_exists? if @project.empty_repo? - render 'projects/empty', layout: user_layout + render 'projects/empty' else @last_push = current_user.recent_push(@project.id) if current_user - render :show, layout: user_layout + render :show end else - render 'projects/no_repo', layout: user_layout + render 'projects/no_repo' end end @@ -160,12 +159,14 @@ class ProjectsController < ApplicationController private - def set_title - @title = 'New Project' - end - - def user_layout - current_user ? 'projects' : 'public_projects' + def determine_layout + if [:new, :create].include?(action_name.to_sym) + 'application' + elsif [:edit, :update].include?(action_name.to_sym) + 'project_settings' + else + 'project' + end end def load_events diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index ad9e9e8487e75004ad3f73fd1bac9e68cf08081c..4e2ea6c5710ff14cca8c75d7f5f764d7b3410cc3 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -1,6 +1,8 @@ class SearchController < ApplicationController include SearchHelper + layout 'search' + def show return if params[:search].nil? || params[:search].blank? diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index a5259466cb8d2b6853b07c27375cbb9e8235235c..cf672c5c0932b05b8a34d20aaed6e8a09460c98f 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -7,14 +7,11 @@ class SnippetsController < ApplicationController # Allow destroy snippet before_action :authorize_admin_snippet!, only: [:destroy] - before_action :set_title - skip_before_action :authenticate_user!, only: [:index, :user_index, :show, :raw] + layout 'snippets' respond_to :html - layout :determine_layout - def index if params[:username].present? @user = User.find_by(username: params[:username]) @@ -98,16 +95,7 @@ class SnippetsController < ApplicationController return render_404 unless can?(current_user, :admin_personal_snippet, @snippet) end - def set_title - @title = 'Snippets' - @title_url = snippets_path - end - def snippet_params params.require(:personal_snippet).permit(:title, :content, :file_name, :private, :visibility_level) end - - def determine_layout - current_user ? 'snippets' : 'public_users' - end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 460cc868b35cee1b7aef1942d4dda40408fc9779..2bb5c338cf60fc119b3083a8e4eb08d902a79a3c 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,7 +1,6 @@ class UsersController < ApplicationController skip_before_action :authenticate_user! before_action :set_user - layout :determine_layout def show @contributed_projects = contributed_projects.joined(@user). @@ -13,9 +12,6 @@ class UsersController < ApplicationController # Collect only groups common for both users @groups = @user.groups & GroupsFinder.new.execute(current_user) - @title = @user.name - @title_url = user_path(@user) - respond_to do |format| format.html @@ -51,14 +47,6 @@ class UsersController < ApplicationController render 'calendar_activities', layout: false end - def determine_layout - if current_user - 'navless' - else - 'public_users' - end - end - private def set_user diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index bc234500000458ed94d118bee01b959c0514f5c2..24263a0f619e45bbba0fa44bff7b88ffe1fbb137 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -34,10 +34,8 @@ module GitlabMarkdownHelper # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch rend = Redcarpet::Render::GitlabHTML.new(self, user_color_scheme_class, { - with_toc_data: true, - safe_links_only: true, - # Handled further down the line by HTML::Pipeline::SanitizationFilter - escape_html: false + # Handled further down the line by Gitlab::Markdown::SanitizationFilter + escape_html: false }.merge(options)) # see https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use @@ -45,7 +43,6 @@ module GitlabMarkdownHelper no_intra_emphasis: true, tables: true, fenced_code_blocks: true, - autolink: true, strikethrough: true, lax_spacing: true, space_after_headers: true, diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index add0a776a6366885eefac034113589c891d2eb5b..3569ac2af635537c852a8d110ae7a42cf5597c79 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -19,24 +19,6 @@ module GroupsHelper end end - def group_head_title - title = @group.name - - title = if current_action?(:issues) - "Issues - " + title - elsif current_action?(:merge_requests) - "Merge requests - " + title - elsif current_action?(:members) - "Members - " + title - elsif current_action?(:edit) - "Settings - " + title - else - title - end - - title - end - def group_settings_page? if current_controller?('groups') current_action?('edit') || current_action?('projects') diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index c3b4731dff303616d9689ca84e3d0686d0d5e425..36d3f371c1b69408a36df65180523ef104780dd8 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -43,17 +43,6 @@ module IssuesHelper end end - def title_for_issue(issue_iid, project = @project) - return '' if project.nil? - - if project.default_issues_tracker? - issue = project.issues.where(iid: issue_iid).first - return issue.title if issue - end - - '' - end - def issue_timestamp(issue) # Shows the created at time and the updated at time if different ts = "#{time_ago_with_tooltip(issue.created_at, 'bottom', 'note_created_ago')}" @@ -110,5 +99,5 @@ module IssuesHelper end # Required for Gitlab::Markdown::IssueReferenceFilter - module_function :url_for_issue, :title_for_issue + module_function :url_for_issue end diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb new file mode 100644 index 0000000000000000000000000000000000000000..01b6a63552c1c00123becdcc5a98c19ee9e7374b --- /dev/null +++ b/app/helpers/page_layout_helper.rb @@ -0,0 +1,26 @@ +module PageLayoutHelper + def page_title(*titles) + @page_title ||= [] + + @page_title.push(*titles.compact) if titles.any? + + @page_title.join(" | ") + end + + def header_title(title = nil, title_url = nil) + if title + @header_title = title + @header_title_url = title_url + else + @header_title_url ? link_to(@header_title, @header_title_url) : @header_title + end + end + + def sidebar(name = nil) + if name + @sidebar = name + else + @sidebar + end + end +end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index c2a7732e6f03dddcc2e2601dc17127088eedbad4..96d2606f1a1ae765492ac37fdf199cd7235ada0d 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -192,46 +192,6 @@ module ProjectsHelper 'unknown' end - def project_head_title - title = @project.name_with_namespace - - title = if current_controller?(:tree) - "#{@project.path}\/#{@path} at #{@ref} - " + title - elsif current_controller?(:issues) - if current_action?(:show) - "Issue ##{@issue.iid} - #{@issue.title} - " + title - else - "Issues - " + title - end - elsif current_controller?(:blob) - if current_action?(:new) || current_action?(:create) - "New file at #{@ref}" - elsif current_action?(:show) - "#{@blob.path} at #{@ref}" - elsif @blob - "Edit file #{@blob.path} at #{@ref}" - end - elsif current_controller?(:commits) - "Commits at #{@ref} - " + title - elsif current_controller?(:merge_requests) - if current_action?(:show) - "Merge request ##{@merge_request.iid} - " + title - else - "Merge requests - " + title - end - elsif current_controller?(:wikis) - "Wiki - " + title - elsif current_controller?(:network) - "Network graph - " + title - elsif current_controller?(:graphs) - "Graphs - " + title - else - title - end - - title - end - def default_url_to_repo(project = nil) project = project || @project current_user ? project.url_to_repo : project.http_url_to_repo diff --git a/app/mailers/devise_mailer.rb b/app/mailers/devise_mailer.rb new file mode 100644 index 0000000000000000000000000000000000000000..5395fe16414f087f048cfa1d2c36dafa57e31f28 --- /dev/null +++ b/app/mailers/devise_mailer.rb @@ -0,0 +1,4 @@ +class DeviseMailer < Devise::Mailer + default from: "GitLab <#{Gitlab.config.gitlab.email_from}>" + default reply_to: Gitlab.config.gitlab.email_reply_to +end diff --git a/app/models/external_issue.rb b/app/models/external_issue.rb index 50efcb32f1b9f93c41dd20e858a9405e97e4543a..85fdb12bfdc7a332d84cc90992ded77a6e027a72 100644 --- a/app/models/external_issue.rb +++ b/app/models/external_issue.rb @@ -15,6 +15,10 @@ class ExternalIssue @issue_identifier.to_s end + def title + "External Issue #{self}" + end + def ==(other) other.is_a?(self.class) && (to_s == other.to_s) end diff --git a/app/models/project.rb b/app/models/project.rb index 397232e98d8a46c0d8ebf57e5ad86b0c2f04a307..e866681aab947e736a0f071f0bd3fccd87bbbe94 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -329,14 +329,18 @@ class Project < ActiveRecord::Base self.id end - def issue_exists?(issue_id) + def get_issue(issue_id) if default_issues_tracker? - self.issues.where(iid: issue_id).first.present? + issues.find_by(iid: issue_id) else - true + ExternalIssue.new(issue_id, self) end end + def issue_exists?(issue_id) + get_issue(issue_id) + end + def default_issue_tracker gitlab_issue_tracker_service || create_gitlab_issue_tracker_service end @@ -350,11 +354,7 @@ class Project < ActiveRecord::Base end def default_issues_tracker? - if external_issue_tracker - false - else - true - end + !external_issue_tracker end def external_issues_trackers diff --git a/app/views/admin/application_settings/show.html.haml b/app/views/admin/application_settings/show.html.haml index 39b66647a5a878754f9afc1ac642ab387d9c91db..1632dd8affa286d298fbe94f1587b3d86920164f 100644 --- a/app/views/admin/application_settings/show.html.haml +++ b/app/views/admin/application_settings/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Settings" %h3.page-title Application settings %hr = render 'form' diff --git a/app/views/admin/applications/edit.html.haml b/app/views/admin/applications/edit.html.haml index e408ae2f29d0647bae76bf1c039e33ec525ff34a..c596866bde210980094f6bc80ce6440e350dfdcf 100644 --- a/app/views/admin/applications/edit.html.haml +++ b/app/views/admin/applications/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @application.name, "Applications" %h3.page-title Edit application - @url = admin_application_path(@application) -= render 'form', application: @application \ No newline at end of file += render 'form', application: @application diff --git a/app/views/admin/applications/index.html.haml b/app/views/admin/applications/index.html.haml index d550278710ebeaf8555308eb868cf9e34f83d55b..fc921a966f3fe7f139ecfb04c9aaf75c97ce259e 100644 --- a/app/views/admin/applications/index.html.haml +++ b/app/views/admin/applications/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Applications" %h3.page-title System OAuth applications %p.light diff --git a/app/views/admin/applications/new.html.haml b/app/views/admin/applications/new.html.haml index 7c62425f19c94bd3bee5c05d9ed9a944b0a2b1a4..6310d89bd6bc5ee05a526d4871f804a65e4e2534 100644 --- a/app/views/admin/applications/new.html.haml +++ b/app/views/admin/applications/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Application" %h3.page-title New application - @url = admin_applications_path -= render 'form', application: @application \ No newline at end of file += render 'form', application: @application diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml index 2abe390ce13e7b853e11d7c6f28766375dd2c1d6..0ea2ffeda9976b5909d9631b0f397dc1b4b5c9cb 100644 --- a/app/views/admin/applications/show.html.haml +++ b/app/views/admin/applications/show.html.haml @@ -1,3 +1,4 @@ +- page_title @application.name, "Applications" %h3.page-title Application: #{@application.name} diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index 4ef8e878a7f1c419f8c89c641842d4739a46a17e..3a01e1151098e8bc3d553ae2e6e9f68a74f428b5 100644 --- a/app/views/admin/background_jobs/show.html.haml +++ b/app/views/admin/background_jobs/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Background Jobs" %h3.page-title Background Jobs %p.light GitLab uses #{link_to "sidekiq", "http://sidekiq.org/"} library for async job processing diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml index 7e29311bf42c6f8d7cf8a6f18f362a11af4ef902..267c9a5292104e39f341fceca1e64c8ccf148c19 100644 --- a/app/views/admin/broadcast_messages/index.html.haml +++ b/app/views/admin/broadcast_messages/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Broadcast Messages" %h3.page-title Broadcast Messages %p.light diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml index 2ae83ab95f7ffe7df832ce3bf3d5a6b7e02964ed..367d25cd6a1a975902fa6bbb29ff290e757297c7 100644 --- a/app/views/admin/deploy_keys/index.html.haml +++ b/app/views/admin/deploy_keys/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Deploy Keys" .panel.panel-default .panel-heading Public deploy keys (#{@deploy_keys.count}) diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml index c00049424c58180927c409f7b7dd7fd1317f5e34..5b46b3222a9cc5a5ffcdf21c72451a0f739f39be 100644 --- a/app/views/admin/deploy_keys/new.html.haml +++ b/app/views/admin/deploy_keys/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Deploy Key" %h3.page-title New public deploy key %hr diff --git a/app/views/admin/deploy_keys/show.html.haml b/app/views/admin/deploy_keys/show.html.haml index cfa2adf92eefb0ab6bf5f9bb8951600768a7d8a4..ea361ca4bdbc471af88e3dcb74643d9b16f35bf4 100644 --- a/app/views/admin/deploy_keys/show.html.haml +++ b/app/views/admin/deploy_keys/show.html.haml @@ -1,3 +1,4 @@ +- page_title @deploy_key.title, "Deploy Keys" .row .col-md-4 .panel.panel-default diff --git a/app/views/admin/groups/edit.html.haml b/app/views/admin/groups/edit.html.haml index 824e51c1cf1340ca4ab2244ea376600257ff4f83..eb09a6328ed39d16d1a2a355899b848c4ac75633 100644 --- a/app/views/admin/groups/edit.html.haml +++ b/app/views/admin/groups/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @group.name, "Groups" %h3.page-title Edit group: #{@group.name} %hr = render 'form' diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml index 4c53ff55708790a7d5e5a9e47df5c3fe91086668..e00b23ad99f5fcea21433abbb73867822a47881d 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Groups" %h3.page-title Groups (#{@groups.total_count}) = link_to 'New Group', new_admin_group_path, class: "btn btn-new pull-right" diff --git a/app/views/admin/groups/new.html.haml b/app/views/admin/groups/new.html.haml index f46f45c5514853c563a4515d52bbda61ba975a41..c81ee552ac3717ecaed1818006273002e80899cf 100644 --- a/app/views/admin/groups/new.html.haml +++ b/app/views/admin/groups/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Group" %h3.page-title New group %hr = render 'form' diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 427f38018b0b67a9244214b3bfb21af5d52c506d..187314872de54c851e4cff2f5c287edcac017863 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -1,3 +1,4 @@ +- page_title @group.name, "Groups" %h3.page-title Group: #{@group.name} diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index 7a9dc113f2a93df806c6aa1d3c6b28c69020f8e1..e74e1e85f4165251dc1f8f7d1cf988c01584397c 100644 --- a/app/views/admin/hooks/index.html.haml +++ b/app/views/admin/hooks/index.html.haml @@ -1,3 +1,4 @@ +- page_title "System Hooks" %h3.page-title System hooks diff --git a/app/views/admin/keys/show.html.haml b/app/views/admin/keys/show.html.haml index 5b23027b3abdbee6c68b0589bf846054c37a5b5e..9ee77c77398bb0d59a79514e04a76efd10c23958 100644 --- a/app/views/admin/keys/show.html.haml +++ b/app/views/admin/keys/show.html.haml @@ -1 +1,2 @@ +- page_title @key.title, "Keys" = render "profiles/keys/key_details", admin: true diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml index 384c6ee9af5e4fe063a5b32d23946d809fec79c1..1484baa78e0aad795d536599e42fe7ef2f90bcd3 100644 --- a/app/views/admin/logs/show.html.haml +++ b/app/views/admin/logs/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Logs" - loggers = [Gitlab::GitLogger, Gitlab::AppLogger, Gitlab::ProductionLogger, Gitlab::SidekiqLogger] %ul.nav.nav-tabs.log-tabs diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 0a13791029d4662a5e69326b51b78078f4b64590..f43d46356fa4c85524499343bed5b5e10f8e095a 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Projects" = render 'shared/show_aside' .row diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index 78684c692c7e1468b5dc85c81622e2fc9ce8b7ed..4c2865ac3f223d1e946feadbeec82fef1cf12ba2 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -1,3 +1,4 @@ +- page_title @project.name_with_namespace, "Projects" %h3.page-title Project: #{@project.name_with_namespace} = link_to edit_project_path(@project), class: "btn pull-right" do diff --git a/app/views/admin/services/edit.html.haml b/app/views/admin/services/edit.html.haml index bcc5832792fea10b70d29a9fb15633f06e001dd0..53d970e33c175c104d06f94d45ecee3ba8c36adf 100644 --- a/app/views/admin/services/edit.html.haml +++ b/app/views/admin/services/edit.html.haml @@ -1 +1,2 @@ +- page_title @service.title, "Service Templates" = render 'form' diff --git a/app/views/admin/services/index.html.haml b/app/views/admin/services/index.html.haml index 0093fb97765b7aa30666f1540a3c8ff74688eb4f..e2377291142f1273697a258e0e350e621f003543 100644 --- a/app/views/admin/services/index.html.haml +++ b/app/views/admin/services/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Service Templates" %h3.page-title Service templates %p.light Service template allows you to set default values for project services diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/users/edit.html.haml index d71d8189c51274626eb34781fc8ecc462964f0a7..a8837d74dd97043adb8300c71d37f04190e892a8 100644 --- a/app/views/admin/users/edit.html.haml +++ b/app/views/admin/users/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @user.name, "Users" %h3.page-title Edit user: #{@user.name} .back-link diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 23a9d76963956e025e0fa6803b94b2222bf8fcf5..fe6484702333c52873e4217bb81ec7e455922413 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Users" = render 'shared/show_aside' .row diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml index 8fbb757f42455c1673a7d25681ee513c07740f62..bfc36ed7373dd998f8990fdd37de4ec585b2c4ac 100644 --- a/app/views/admin/users/new.html.haml +++ b/app/views/admin/users/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New User" %h3.page-title New user %hr diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 3524f04c5ed5862b12adffb43dfec1f507a8a9fb..7fc85206109d2472d77e8a9c84de192544e8e954 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -1,3 +1,4 @@ +- page_title @user.name, "Users" %h3.page-title User: = @user.name diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml index 0cb7f764fab43acc98833a0a3e5381ef3ad9a4ad..5ecd53cff8443c00f3589107336b6a59d70ed2f1 100644 --- a/app/views/dashboard/groups/index.html.haml +++ b/app/views/dashboard/groups/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Groups" %h3.page-title Group Membership - if current_user.can_create_group? diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 62cc80a30dc866d706c7468df14a816c63e5cb2b..dfdf0d68c8f426f4e04c12bec9d1ef22664e2419 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -1,3 +1,4 @@ +- page_title "Issues" = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, issues_dashboard_url(format: :atom, private_token: current_user.private_token), title: "#{current_user.name} issues") diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index 97a42461b4e0f54d32a91c139bf1ac3818f1f46b..a7e1b08a0a4e38a6d5065026a662e7ceab96d572 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -1,3 +1,4 @@ +- page_title "Merge Requests" %h3.page-title Merge Requests diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml index 9944c0df8152abe335797699479d9e1175b3e9bf..9a9a5e139a44f72333c0043cd3b615f2d7dcace0 100644 --- a/app/views/dashboard/milestones/index.html.haml +++ b/app/views/dashboard/milestones/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Milestones" %h3.page-title Milestones %span.pull-right #{@dashboard_milestones.count} milestones diff --git a/app/views/dashboard/milestones/show.html.haml b/app/views/dashboard/milestones/show.html.haml index 57cce9ab749ec85fe3e65118a0864c01311c4b72..24f0bcb60d5c9d29ffd8bca42ab30644b67089cb 100644 --- a/app/views/dashboard/milestones/show.html.haml +++ b/app/views/dashboard/milestones/show.html.haml @@ -1,3 +1,4 @@ +- page_title @dashboard_milestone.title, "Milestones" %h4.page-title .issue-box{ class: "issue-box-#{@dashboard_milestone.closed? ? 'closed' : 'open'}" } - if @dashboard_milestone.closed? diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml index 67943f2267b2037c2b9addbf7f646ccc36b00a4e..8aaa0a7f071582794bbe9fbcc2179b7bcedd8829 100644 --- a/app/views/dashboard/projects/starred.html.haml +++ b/app/views/dashboard/projects/starred.html.haml @@ -1,3 +1,4 @@ +- page_title "Starred Projects" - if @projects.any? = render 'shared/show_aside' diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index d3e37f7494c99a4455b05e95bf2aa4804a307dde..42cfbbf84f2b731d4f16e1a5c8f79820149cac0d 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Sign up" = render 'devise/shared/signup_box' -= render 'devise/shared/sign_in_link' \ No newline at end of file += render 'devise/shared/sign_in_link' diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index 89e4e229ac0dd3d1b5c91d65b03f037a23cc79ec..dbc8eda61961b8cae837da916870e0a67d47f51f 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Sign in" %div - if signin_enabled? || ldap_enabled? = render 'devise/shared/signin_box' diff --git a/app/views/doorkeeper/applications/edit.html.haml b/app/views/doorkeeper/applications/edit.html.haml index 61584eb9c498af026e0e0f97767639830a5c3555..fb6aa30acee484c715027673468ff9b1f3083a3c 100644 --- a/app/views/doorkeeper/applications/edit.html.haml +++ b/app/views/doorkeeper/applications/edit.html.haml @@ -1,2 +1,3 @@ +- page_title "Edit", @application.name, "Applications" %h3.page-title Edit application -= render 'form', application: @application \ No newline at end of file += render 'form', application: @application diff --git a/app/views/doorkeeper/applications/index.html.haml b/app/views/doorkeeper/applications/index.html.haml index e5be4b4bcac03d41252ecc84df4bc7ee5ce6f577..3b0b19107ca53612bb61fced036d43bea48b1b4f 100644 --- a/app/views/doorkeeper/applications/index.html.haml +++ b/app/views/doorkeeper/applications/index.html.haml @@ -1,3 +1,4 @@ +- 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 @@ -13,4 +14,4 @@ %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 \ No newline at end of file + %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 82e78b4af132472bfe0ba411d4e67b25b5781baf..80340aca54cecfd832202359055c59ad7821a680 100644 --- a/app/views/doorkeeper/applications/show.html.haml +++ b/app/views/doorkeeper/applications/show.html.haml @@ -1,3 +1,4 @@ +- page_title @application.name, "Applications" %h3.page-title Application: #{@application.name} diff --git a/app/views/errors/access_denied.html.haml b/app/views/errors/access_denied.html.haml index a1d8664c4ce216ee03702560d9809d58b7e27bb6..012e9857642ca898cec37e0f05b4f14e78fedf52 100644 --- a/app/views/errors/access_denied.html.haml +++ b/app/views/errors/access_denied.html.haml @@ -1,3 +1,4 @@ +- page_title "Access Denied" %h1 403 %h3 Access Denied %hr diff --git a/app/views/errors/encoding.html.haml b/app/views/errors/encoding.html.haml index 64c7451a8dabba140c03f46dd6190760b0f24510..90cfbebfcc67212f86b7c0ad27407c3c5051eea0 100644 --- a/app/views/errors/encoding.html.haml +++ b/app/views/errors/encoding.html.haml @@ -1,3 +1,4 @@ +- page_title "Encoding Error" %h1 500 %h3 Encoding Error %hr diff --git a/app/views/errors/git_not_found.html.haml b/app/views/errors/git_not_found.html.haml index 189e53bca55b7ae44d642591a49d646c63927882..ff5d4cc1506f57a541c6990e9b33d28cda777e7e 100644 --- a/app/views/errors/git_not_found.html.haml +++ b/app/views/errors/git_not_found.html.haml @@ -1,3 +1,4 @@ +- page_title "Git Resource Not Found" %h1 404 %h3 Git Resource Not found %hr diff --git a/app/views/errors/not_found.html.haml b/app/views/errors/not_found.html.haml index 7bf88f592cf621779b42b1198bdb62354db0a7f1..3756b98ebb2e59148b3c91b38212e3259e72e714 100644 --- a/app/views/errors/not_found.html.haml +++ b/app/views/errors/not_found.html.haml @@ -1,3 +1,4 @@ +- page_title "Not Found" %h1 404 %h3 The resource you were looking for doesn't exist. %hr diff --git a/app/views/errors/omniauth_error.html.haml b/app/views/errors/omniauth_error.html.haml index f3c8221a9d98c970d0415cd2250008c8a08c9682..3e70e98a24c55456052dc119d2235f8927e50c05 100644 --- a/app/views/errors/omniauth_error.html.haml +++ b/app/views/errors/omniauth_error.html.haml @@ -1,3 +1,4 @@ +- page_title "Auth Error" %h1 422 %h3 Sign-in using #{@provider} auth failed %hr diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml index 2ea6cb186558187b19d27566ee9143ebe291b419..c05d45e010005bda48febd63f92e97d63f6b5873 100644 --- a/app/views/explore/groups/index.html.haml +++ b/app/views/explore/groups/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Groups" .clearfix .pull-left = form_tag explore_groups_path, method: :get, class: 'form-inline form-tiny' do |f| diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml index 5086b58cd03e93e359fb991457a4e0204df4455d..ba2276f51ce722da1353750696b49b36e28802b1 100644 --- a/app/views/explore/projects/index.html.haml +++ b/app/views/explore/projects/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Projects" .clearfix = render 'filter' diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml index 420f069375660faba0c25edee18f7de62ec54224..b5d146b1f2fe296769b52f6b4a5576f3b56d91ce 100644 --- a/app/views/explore/projects/starred.html.haml +++ b/app/views/explore/projects/starred.html.haml @@ -1,3 +1,4 @@ +- page_title "Starred Projects" .explore-trending-block %p.lead %i.fa.fa-star diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml index 18749ac00ae661ab21b700d603dfaf211b4065b5..5ae2653fede07cae8a0bc6f05d772a8d993a6fe6 100644 --- a/app/views/explore/projects/trending.html.haml +++ b/app/views/explore/projects/trending.html.haml @@ -1,3 +1,4 @@ +- page_title "Trending Projects" .explore-title %h3 Explore GitLab diff --git a/app/views/groups/_settings_nav.html.haml b/app/views/groups/_settings_nav.html.haml deleted file mode 100644 index f93caf90076666c3bec29a031dce33145115baf6..0000000000000000000000000000000000000000 --- a/app/views/groups/_settings_nav.html.haml +++ /dev/null @@ -1,11 +0,0 @@ -%ul.sidebar-subnav - = nav_link(path: 'groups#edit') do - = link_to edit_group_path(@group), title: 'Group', data: {placement: 'right'} do - = icon('pencil-square-o') - %span - Group - = nav_link(path: 'groups#projects') do - = link_to projects_group_path(@group), title: 'Projects', data: {placement: 'right'} do - = icon('folder') - %span - Projects diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml index 49e7180bf9873a6d171a77481f04bfc5379f56a9..85179d4c4a2b97e706ebe610b8dae847c93db298 100644 --- a/app/views/groups/edit.html.haml +++ b/app/views/groups/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Settings" .panel.panel-default .panel-heading %strong= @group.name diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index c0c9cd170ad6d717747fc8985bd2f27f7e08cc8a..903ca877218cf66a410a992cf3d382563f2c7255 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Members" - show_roles = should_user_see_group_roles?(current_user, @group) %h3.page-title diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml index cf0da2da46696b37a2f34f9c0750c94a69bb5d15..6a3da6adacf47bd0299dd6bc406bbff3b66fbcbd 100644 --- a/app/views/groups/issues.html.haml +++ b/app/views/groups/issues.html.haml @@ -1,3 +1,4 @@ +- page_title "Issues" = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues") diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml index 1ad74905636f7f3b0637696bcaa6262b36ab4766..268f33d57618a179b3cc9172a4a6ec97f5505b99 100644 --- a/app/views/groups/merge_requests.html.haml +++ b/app/views/groups/merge_requests.html.haml @@ -1,3 +1,4 @@ +- page_title "Merge Requests" %h3.page-title Merge Requests diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index 008d5a6bd22486a89388d9e5f756255b50428297..385222fa5b7784a95152304e2dd7a9e77c4bdbe3 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Milestones" %h3.page-title Milestones %span.pull-right #{@group_milestones.count} milestones diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml index fb32f2caa4c8bcb7d5c4523257327280884c7d31..6c41cd6b9e4316c43a6122e0d246404288a3891b 100644 --- a/app/views/groups/milestones/show.html.haml +++ b/app/views/groups/milestones/show.html.haml @@ -1,3 +1,4 @@ +- page_title @group_milestone.title, "Milestones" %h4.page-title .issue-box{ class: "issue-box-#{@group_milestone.closed? ? 'closed' : 'open'}" } - if @group_milestone.closed? diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 6e17cdaef6f9c9a1870b74c592e2e359b976c607..edb882bea19a24deef769ffee0d59a48f67e6ef2 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -1,3 +1,5 @@ +- page_title 'New Group' +- header_title 'New Group' = form_for @group, html: { class: 'group-form form-horizontal' } do |f| - if @group.errors.any? .alert.alert-danger diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml index 0d547984cc9403f459493374020e6660b263849b..6b7efa83dead48eb166f9d4943060dd02d0b96fd 100644 --- a/app/views/groups/projects.html.haml +++ b/app/views/groups/projects.html.haml @@ -1,3 +1,4 @@ +- page_title "Projects" .panel.panel-default .panel-heading %strong= @group.name diff --git a/app/views/help/show.html.haml b/app/views/help/show.html.haml index cc1be6a717aeaf68026f078c2d81629702a9678d..8551496b98a3107b7c6e9035ce724a9812ae142a 100644 --- a/app/views/help/show.html.haml +++ b/app/views/help/show.html.haml @@ -1,2 +1,3 @@ +- page_title @file.humanize, *@category.split("/").reverse.map(&:humanize) .documentation.wiki = markdown @markdown.gsub('$your_email', current_user.email) diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml index 246a6c1bdfd5dbd46bd4d7f915e9ec9e8a9b1317..7c89457ace3885129eaea47487e560ead6dec74a 100644 --- a/app/views/help/ui.html.haml +++ b/app/views/help/ui.html.haml @@ -1,3 +1,4 @@ +- page_title "UI Development Kit", "Help" - lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed fermentum nisi sapien, non consequat lectus aliquam ultrices. Suspendisse sodales est euismod nunc condimentum, a consectetur diam ornare." .gitlab-ui-dev-kit diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index 4e49bbbc7fa1184bb16fd77049776d82eab15893..9d2858e4e727a027a3b776b117c574411864949a 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -1,3 +1,4 @@ +- page_title "Bitbucket import" %h3.page-title %i.fa.fa-bitbucket Import projects from Bitbucket diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml index f0bc3e6b1ac91abca4c2510d93712920526381fd..ef5524982390fe4817753d043bb934157cd39601 100644 --- a/app/views/import/github/status.html.haml +++ b/app/views/import/github/status.html.haml @@ -1,3 +1,4 @@ +- page_title "GitHub import" %h3.page-title %i.fa.fa-github Import projects from GitHub diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml index 33b0a21acf3b187e1c1d996c7fd3f57a6d5463f5..727f3c7e7fa69b1ace9ff715880c72d012d7f4d4 100644 --- a/app/views/import/gitlab/status.html.haml +++ b/app/views/import/gitlab/status.html.haml @@ -1,3 +1,4 @@ +- page_title "GitLab.com import" %h3.page-title %i.fa.fa-heart Import projects from GitLab.com diff --git a/app/views/import/gitorious/status.html.haml b/app/views/import/gitorious/status.html.haml index 78c5e957be0f3d1feb65952da4de5c3a9ad8c487..bff7ee7c85d657e532cb754f5a9cb4de1953fd52 100644 --- a/app/views/import/gitorious/status.html.haml +++ b/app/views/import/gitorious/status.html.haml @@ -1,3 +1,4 @@ +- page_title "Gitorious import" %h3.page-title %i.icon-gitorious.icon-gitorious-big Import projects from Gitorious.org diff --git a/app/views/import/google_code/new.html.haml b/app/views/import/google_code/new.html.haml index ce78fec205f1683207e0a21b2e7058a5266d89d2..9c64e0a009fb73931f3845306911929d33b5ef6e 100644 --- a/app/views/import/google_code/new.html.haml +++ b/app/views/import/google_code/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Google Code import" %h3.page-title %i.fa.fa-google Import projects from Google Code diff --git a/app/views/import/google_code/new_user_map.html.haml b/app/views/import/google_code/new_user_map.html.haml index 9c6824ecad7e49de7ff039f5093eacbb12041e3b..e53ebda7dc19683ab7d601aa73a4735d85504a20 100644 --- a/app/views/import/google_code/new_user_map.html.haml +++ b/app/views/import/google_code/new_user_map.html.haml @@ -1,3 +1,4 @@ +- page_title "User map", "Google Code import" %h3.page-title %i.fa.fa-google Import projects from Google Code diff --git a/app/views/import/google_code/status.html.haml b/app/views/import/google_code/status.html.haml index 2013b8c03c6e59489e27b6ee11650c89dbcc6b16..e8ec79e72f7fed286f5c4bfa171f48cfa418a02a 100644 --- a/app/views/import/google_code/status.html.haml +++ b/app/views/import/google_code/status.html.haml @@ -1,16 +1,21 @@ +- page_title "Google Code import" %h3.page-title %i.fa.fa-google Import projects from Google Code -%p.light - Select projects you want to import. -%p.light - Optionally, you can - = link_to "customize", new_user_map_import_google_code_path - how Google Code email addresses and usernames are imported into GitLab. -%hr -%p - = button_tag 'Import all projects', class: "btn btn-success js-import-all" +- if @repos.any? + %p.light + Select projects you want to import. + %p.light + Optionally, you can + = link_to "customize", new_user_map_import_google_code_path + how Google Code email addresses and usernames are imported into GitLab. + %hr + %p + - if @incompatible_repos.any? + = button_tag 'Import all compatible projects', class: "btn btn-success js-import-all" + - else + = button_tag 'Import all projects', class: "btn btn-success js-import-all" %table.table.import-jobs %thead @@ -44,6 +49,22 @@ = "#{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 + One or more of your Google Code projects cannot be imported into GitLab + directly because they use Subversion or Mercurial for version control, + rather than Git. Please convert them to Git on Google Code, and go + through the + = link_to "import flow", new_import_google_code_path + again. :coffeescript new ImporterStatus("#{jobs_import_google_code_path}", "#{import_google_code_path}") diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml index ab0ecffe4d2b24524efc69007cfaa9a5324b7d3a..2fd4859c1c628e50158caa477d424f21c1b993df 100644 --- a/app/views/invites/show.html.haml +++ b/app/views/invites/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Invitation" %h3.page-title Invitation %p diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index f72882d883e77a313b88d132afad04f8209ce9bd..b1a57d9824e21dba3a3129aa142a200a1d4d6ca4 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -1,11 +1,10 @@ +- page_title "GitLab" %head %meta{charset: "utf-8"} %meta{'http-equiv' => 'X-UA-Compatible', content: 'IE=edge'} %meta{content: "GitLab Community Edition", name: "description"} - %title - = "#{title} | " if defined?(title) - GitLab + %title= page_title = favicon_link_tag 'favicon.ico' = stylesheet_link_tag "application", :media => "all" diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 0fa2ec9824dc44f2be60197f0d1d008d4810a217..5c55bdb546500fa4239a4a3ae5f9b0af7ce3aded 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -1,8 +1,8 @@ .page-with-sidebar{ class: nav_sidebar_class } = render "layouts/broadcast" .sidebar-wrapper - - if defined?(sidebar) - = render(sidebar) + - if defined?(sidebar) && sidebar + = render "layouts/nav/#{sidebar}" - elsif current_user = render 'layouts/nav/dashboard' .collapse-nav diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index ab84e87c300209e2a7d3a42c7c15e9d003d86f6c..1c738719bd84b3782c7e0cd60aa88a4c2cea6cbf 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -1,6 +1,5 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: "Admin area" - %body{class: "#{app_theme} admin", :'data-page' => body_data_page} - = render "layouts/head_panel", title: link_to("Admin area", admin_root_path) - = render 'layouts/page', sidebar: 'layouts/nav/admin' +- page_title "Admin area" +- header_title "Admin area", admin_root_path +- sidebar "admin" + += render template: "layouts/application" diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 6bd8ac4adb85e4e9b9e6d8469963c36b0dd20fb0..a97feeb1ecdc9caf4afc63eb2321d5eaadfd3c8b 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,6 +1,10 @@ !!! 5 %html{ lang: "en"} - = render "layouts/head", title: "Dashboard" - %body{class: "#{app_theme} application", :'data-page' => body_data_page } - = render "layouts/head_panel", title: link_to("Dashboard", root_path) - = render 'layouts/page', sidebar: 'layouts/nav/dashboard' + = render "layouts/head" + %body{class: "#{app_theme}", :'data-page' => body_data_page} + - if current_user + = render "layouts/head_panel", title: header_title + - else + = render "layouts/public_head_panel", title: header_title + + = render 'layouts/page', sidebar: sidebar diff --git a/app/views/layouts/dashboard.html.haml b/app/views/layouts/dashboard.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..c72eca10bf4c379635b91a52a85a48a2e0a8a4b7 --- /dev/null +++ b/app/views/layouts/dashboard.html.haml @@ -0,0 +1,5 @@ +- page_title "Dashboard" +- header_title "Dashboard", root_path +- sidebar "dashboard" + += render template: "layouts/application" diff --git a/app/views/layouts/errors.html.haml b/app/views/layouts/errors.html.haml index e51fd4cb8208e4e758d1a3776b55bdd97f922f95..aa0f3f0a8194b6c54d72685b994535adb77da745 100644 --- a/app/views/layouts/errors.html.haml +++ b/app/views/layouts/errors.html.haml @@ -1,6 +1,6 @@ !!! 5 %html{ lang: "en"} - = render "layouts/head", title: "Error" + = render "layouts/head" %body{class: "#{app_theme} application"} = render "layouts/head_panel", title: "" if current_user .container.navless-container diff --git a/app/views/layouts/explore.html.haml b/app/views/layouts/explore.html.haml index ca79382324ecaf47f7f3f354a839e72647bfa25e..56bb92a536edbb41d2b4d2fc295a14d92d3f5d3b 100644 --- a/app/views/layouts/explore.html.haml +++ b/app/views/layouts/explore.html.haml @@ -1,12 +1,5 @@ -- page_title = 'Explore GitLab' -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: page_title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/broadcast" - - if current_user - = render "layouts/head_panel", title: link_to(page_title, explore_root_path) - - else - = render "layouts/public_head_panel", title: link_to(page_title, explore_root_path) +- page_title "Explore" +- header_title "Explore GitLab", explore_root_path +- sidebar "explore" - = render 'layouts/page', sidebar: 'layouts/nav/explore' += render template: "layouts/application" diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml index f4a6bee15f68c6e6022179bb4378e7bca15a64af..5edc03129d233d0c77bdea85f2b477ec607c1233 100644 --- a/app/views/layouts/group.html.haml +++ b/app/views/layouts/group.html.haml @@ -1,6 +1,5 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: group_head_title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/head_panel", title: link_to(@group.name, group_path(@group)) - = render 'layouts/page', sidebar: 'layouts/nav/group' +- page_title @group.name +- header_title @group.name, group_path(@group) +- sidebar "group" + += render template: "layouts/application" diff --git a/app/views/layouts/help.html.haml b/app/views/layouts/help.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..224b24befbe8724f7b0af25a4e752c08ad654467 --- /dev/null +++ b/app/views/layouts/help.html.haml @@ -0,0 +1,4 @@ +- page_title "Help" +- header_title "Help", help_path + += render template: "layouts/application" diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml index 74a8526dbd7f10a62c7729755fb94a618936f737..62f0579d48b9fad2f2b7b06d3b192eca6f5ce460 100644 --- a/app/views/layouts/nav/_group.html.haml +++ b/app/views/layouts/nav/_group.html.haml @@ -39,4 +39,15 @@ = icon ('angle-down fw') - if group_settings_page? - = render 'groups/settings_nav' + %ul.sidebar-subnav + = nav_link(path: 'groups#edit') do + = link_to edit_group_path(@group), title: 'Group', data: {placement: 'right'} do + = icon('pencil-square-o') + %span + Group + = nav_link(path: 'groups#projects') do + = link_to projects_group_path(@group), title: 'Projects', data: {placement: 'right'} do + = icon('folder') + %span + Projects + diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index 01b3d70194fcb8225dfc969bf1c718099ba549a5..172f5197b24b0d5a74dc2958689e73b4926c648c 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -1,97 +1,85 @@ %ul.project-navigation.nav.nav-sidebar - - if @project_settings_nav - = nav_link do - = link_to project_path(@project), title: 'Back to project', data: {placement: 'right'} do - = icon('caret-square-o-left fw') + = nav_link(path: 'projects#show', html_options: {class: 'home'}) do + = link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do + = icon('dashboard fw') + %span + Project + - if project_nav_tab? :files + = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do + = link_to namespace_project_tree_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Files', class: 'shortcuts-tree', data: {placement: 'right'} do + = icon('files-o fw') %span - Back to project + Files - %li.separate-item - - = render 'projects/settings_nav' - - - else - = nav_link(path: 'projects#show', html_options: {class: 'home'}) do - = link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do - = icon('dashboard fw') + - if project_nav_tab? :commits + = nav_link(controller: %w(commit commits compare repositories tags branches)) do + = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do + = icon('history fw') %span - Project - - if project_nav_tab? :files - = nav_link(controller: %w(tree blob blame edit_tree new_tree)) do - = link_to namespace_project_tree_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Files', class: 'shortcuts-tree', data: {placement: 'right'} do - = icon('files-o fw') - %span - Files - - - if project_nav_tab? :commits - = nav_link(controller: %w(commit commits compare repositories tags branches)) do - = link_to namespace_project_commits_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do - = icon('history fw') - %span - Commits + Commits - - if project_nav_tab? :network - = nav_link(controller: %w(network)) do - = link_to namespace_project_network_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Network', class: 'shortcuts-network', data: {placement: 'right'} do - = icon('code-fork fw') - %span - Network + - if project_nav_tab? :network + = nav_link(controller: %w(network)) do + = link_to namespace_project_network_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Network', class: 'shortcuts-network', data: {placement: 'right'} do + = icon('code-fork fw') + %span + Network - - if project_nav_tab? :graphs - = nav_link(controller: %w(graphs)) do - = link_to namespace_project_graph_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Graphs', class: 'shortcuts-graphs', data: {placement: 'right'} do - = icon('area-chart fw') - %span - Graphs + - if project_nav_tab? :graphs + = nav_link(controller: %w(graphs)) do + = link_to namespace_project_graph_path(@project.namespace, @project, @ref || @repository.root_ref), title: 'Graphs', class: 'shortcuts-graphs', data: {placement: 'right'} do + = icon('area-chart fw') + %span + Graphs - - if project_nav_tab? :milestones - = nav_link(controller: :milestones) do - = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones', data: {placement: 'right'} do - = icon('clock-o fw') - %span - Milestones + - if project_nav_tab? :milestones + = nav_link(controller: :milestones) do + = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones', data: {placement: 'right'} do + = icon('clock-o fw') + %span + Milestones - - if project_nav_tab? :issues - = nav_link(controller: :issues) do - = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues', data: {placement: 'right'} do - = icon('exclamation-circle fw') - %span - Issues - - if @project.default_issues_tracker? - %span.count.issue_counter= @project.issues.opened.count + - if project_nav_tab? :issues + = nav_link(controller: :issues) do + = link_to url_for_project_issues(@project, only_path: true), title: 'Issues', class: 'shortcuts-issues', data: {placement: 'right'} do + = icon('exclamation-circle fw') + %span + Issues + - if @project.default_issues_tracker? + %span.count.issue_counter= @project.issues.opened.count - - if project_nav_tab? :merge_requests - = nav_link(controller: :merge_requests) do - = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests', data: {placement: 'right'} do - = icon('tasks fw') - %span - Merge Requests - %span.count.merge_counter= @project.merge_requests.opened.count + - if project_nav_tab? :merge_requests + = nav_link(controller: :merge_requests) do + = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests', data: {placement: 'right'} do + = icon('tasks fw') + %span + Merge Requests + %span.count.merge_counter= @project.merge_requests.opened.count - - if project_nav_tab? :labels - = nav_link(controller: :labels) do - = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels', data: {placement: 'right'} do - = icon('tags fw') - %span - Labels + - if project_nav_tab? :labels + = nav_link(controller: :labels) do + = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels', data: {placement: 'right'} do + = icon('tags fw') + %span + Labels - - if project_nav_tab? :wiki - = nav_link(controller: :wikis) do - = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki', data: {placement: 'right'} do - = icon('book fw') - %span - Wiki + - if project_nav_tab? :wiki + = nav_link(controller: :wikis) do + = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki', data: {placement: 'right'} do + = icon('book fw') + %span + Wiki - - if project_nav_tab? :snippets - = nav_link(controller: :snippets) do - = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets', data: {placement: 'right'} do - = icon('file-text-o fw') - %span - Snippets + - if project_nav_tab? :snippets + = nav_link(controller: :snippets) do + = link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets', data: {placement: 'right'} do + = icon('file-text-o fw') + %span + Snippets - - if project_nav_tab? :settings - = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do - = link_to edit_project_path(@project), title: 'Settings', class: 'stat-tab tab no-highlight', data: {placement: 'right'} do - = icon('cogs fw') - %span - Settings + - if project_nav_tab? :settings + = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do + = link_to edit_project_path(@project), title: 'Settings', class: 'stat-tab tab no-highlight', data: {placement: 'right'} do + = icon('cogs fw') + %span + Settings diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..21260302a09a2c2cf16c24322bf76f0d34b7ed73 --- /dev/null +++ b/app/views/layouts/nav/_project_settings.html.haml @@ -0,0 +1,41 @@ +%ul.project-navigation.nav.nav-sidebar + = nav_link do + = link_to project_path(@project), title: 'Back to project', data: {placement: 'right'} do + = icon('caret-square-o-left fw') + %span + Back to project + + %li.separate-item + + %ul.project-settings-nav.sidebar-subnav + = nav_link(path: 'projects#edit') do + = link_to edit_project_path(@project), title: 'Project', class: 'stat-tab tab', data: {placement: 'right'} do + = icon('pencil-square-o') + %span + Project + = nav_link(controller: [:project_members, :teams]) do + = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab', data: {placement: 'right'} do + = icon('users') + %span + Members + = nav_link(controller: :deploy_keys) do + = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys', data: {placement: 'right'} do + = icon('key') + %span + Deploy Keys + = nav_link(controller: :hooks) do + = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Web Hooks', data: {placement: 'right'} do + = icon('link') + %span + Web Hooks + = nav_link(controller: :services) do + = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services', data: {placement: 'right'} do + = icon('cogs') + %span + Services + = nav_link(controller: :protected_branches) do + = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches', data: {placement: 'right'} do + = icon('lock') + %span + Protected branches + diff --git a/app/views/layouts/nav/_snippets.html.haml b/app/views/layouts/nav/_snippets.html.haml index 0de3a9e5bb77ac87b798cbd293c5c88fbf33a27b..458b76a2c99808eb02cc42a8c4ad4ca2c3de35ab 100644 --- a/app/views/layouts/nav/_snippets.html.haml +++ b/app/views/layouts/nav/_snippets.html.haml @@ -1,9 +1,10 @@ %ul.nav.nav-sidebar - = nav_link(path: user_snippets_path(current_user), html_options: {class: 'home'}) do - = link_to user_snippets_path(current_user), title: 'Your snippets', data: {placement: 'right'} do - = icon('dashboard fw') - %span - Your Snippets + - if current_user + = nav_link(path: user_snippets_path(current_user), html_options: {class: 'home'}) do + = link_to user_snippets_path(current_user), title: 'Your snippets', data: {placement: 'right'} do + = icon('dashboard fw') + %span + Your Snippets = nav_link(path: snippets_path) do = link_to snippets_path, title: 'Discover snippets', data: {placement: 'right'} do = icon('globe fw') diff --git a/app/views/layouts/navless.html.haml b/app/views/layouts/navless.html.haml deleted file mode 100644 index 10a0fcea2f80751d75041770a0d0758225c72c34..0000000000000000000000000000000000000000 --- a/app/views/layouts/navless.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: @title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/broadcast" - = render "layouts/head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title - = render 'layouts/page' diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index 2b5be7fc37202a5ea3735941d94a44a6f96c055d..9799b4cc4d72c4f31d08dcf51ea499664097e3fd 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -1,6 +1,5 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: "Profile" - %body{class: "#{app_theme} profile", :'data-page' => body_data_page} - = render "layouts/head_panel", title: link_to("Profile", profile_path) - = render 'layouts/page', sidebar: 'layouts/nav/profile' +- page_title "Profile" +- header_title "Profile", profile_path +- sidebar "profile" + += render template: "layouts/application" diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..4aeb9d397d2aa73a504077a6e3d2dc21eb241660 --- /dev/null +++ b/app/views/layouts/project.html.haml @@ -0,0 +1,8 @@ +- page_title @project.name_with_namespace +- header_title project_title(@project) +- sidebar "project" unless sidebar + +- content_for :embedded_scripts do + = render "layouts/init_auto_complete" if current_user + += render template: "layouts/application" diff --git a/app/views/layouts/project_settings.html.haml b/app/views/layouts/project_settings.html.haml index 0a0039dec169e5f5d5d047685ebf29e1d7fbc8a3..4340166833487461454281ad4759f490380165c1 100644 --- a/app/views/layouts/project_settings.html.haml +++ b/app/views/layouts/project_settings.html.haml @@ -1,8 +1,4 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: @project.name_with_namespace - %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } - = render "layouts/head_panel", title: project_title(@project) - = render "layouts/init_auto_complete" - - @project_settings_nav = true - = render 'layouts/page', sidebar: 'layouts/nav/project' +- page_title "Settings" +- sidebar "project_settings" + += render template: "layouts/project" diff --git a/app/views/layouts/projects.html.haml b/app/views/layouts/projects.html.haml deleted file mode 100644 index dde0964f47f4961035bcf2467b24438ee0602404..0000000000000000000000000000000000000000 --- a/app/views/layouts/projects.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: project_head_title - %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } - = render "layouts/head_panel", title: project_title(@project) - = render "layouts/init_auto_complete" - = render 'layouts/page', sidebar: 'layouts/nav/project' diff --git a/app/views/layouts/public_group.html.haml b/app/views/layouts/public_group.html.haml deleted file mode 100644 index b9b1d03e08ee8a05288b207fcfbad755778f6da4..0000000000000000000000000000000000000000 --- a/app/views/layouts/public_group.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: group_head_title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/public_head_panel", title: link_to(@group.name, group_path(@group)) - = render 'layouts/page', sidebar: 'layouts/nav/group' diff --git a/app/views/layouts/public_projects.html.haml b/app/views/layouts/public_projects.html.haml deleted file mode 100644 index 04fa7c84e73c75ccaf700be683062e90fa0ce75e..0000000000000000000000000000000000000000 --- a/app/views/layouts/public_projects.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: @project.name_with_namespace - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/public_head_panel", title: project_title(@project) - = render 'layouts/page', sidebar: 'layouts/nav/project' diff --git a/app/views/layouts/public_users.html.haml b/app/views/layouts/public_users.html.haml deleted file mode 100644 index 71c16bd168418d1a0771abe37c692c26f12178c5..0000000000000000000000000000000000000000 --- a/app/views/layouts/public_users.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: @title - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/public_head_panel", title: defined?(@title_url) ? link_to(@title, @title_url) : @title - = render 'layouts/page' diff --git a/app/views/layouts/search.html.haml b/app/views/layouts/search.html.haml index 4b526686be4058a2849798823a76ccfcbb350ada..fd4c7ad21a71501bc03cf01dffb42e56ce38305d 100644 --- a/app/views/layouts/search.html.haml +++ b/app/views/layouts/search.html.haml @@ -1,6 +1,4 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: "Search" - %body{class: "#{app_theme} application", :'data-page' => body_data_page} - = render "layouts/head_panel", title: link_to("Search", search_path) - = render 'layouts/page' +- page_title "Search" +- header_title "Search", search_path + += render template: "layouts/application" diff --git a/app/views/layouts/snippets.html.haml b/app/views/layouts/snippets.html.haml index fbd29eb23a75d5e52f7aa3f0f19b0c9f3534395e..9b0f40073ab79061cc7da12c3ff391377ffc6fa0 100644 --- a/app/views/layouts/snippets.html.haml +++ b/app/views/layouts/snippets.html.haml @@ -1,6 +1,5 @@ -!!! 5 -%html{ lang: "en"} - = render "layouts/head", title: "Dashboard" - %body{class: "#{app_theme} application", :'data-page' => body_data_page } - = render "layouts/head_panel", title: link_to("Snippets", snippets_path) - = render 'layouts/page', sidebar: 'layouts/nav/snippets' +- page_title 'Snippets' +- header_title 'Snippets', snippets_path +- sidebar "snippets" + += render template: "layouts/application" diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index 5bffb4acc1d7530c08a00d699be68843c1680684..1c3a3d68aca912979630929f70584b5e2c52dc09 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Account" - if current_user.ldap_user? .alert.alert-info Some options are unavailable for LDAP accounts diff --git a/app/views/profiles/applications.html.haml b/app/views/profiles/applications.html.haml index 97e98948f36647b7021e32cd3bd7e769365f75c0..c4f6f59624bc5a97f7b71346e613bbd3ea1b73b4 100644 --- a/app/views/profiles/applications.html.haml +++ b/app/views/profiles/applications.html.haml @@ -1,3 +1,4 @@ +- page_title "Applications" %h3.page-title Application Settings %p.light diff --git a/app/views/profiles/design.html.haml b/app/views/profiles/design.html.haml index 646576c3164ecd7db6fd3f4fe08d4f6d1540a486..af284f6040964a59b2b3153916a7159733d1cd36 100644 --- a/app/views/profiles/design.html.haml +++ b/app/views/profiles/design.html.haml @@ -1,3 +1,4 @@ +- page_title "Design" %h3.page-title Design Settings %p.light diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml index 09f290429eacb2f97599daf3ea46e26df180fd15..c17e01425d8006e0721d9594f5f2ea58b60d74bf 100644 --- a/app/views/profiles/emails/index.html.haml +++ b/app/views/profiles/emails/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Emails" %h3.page-title Email Settings %p.light diff --git a/app/views/profiles/history.html.haml b/app/views/profiles/history.html.haml index b1ab433f48fb90552dd70f288b7a62fd86c34e50..b414fb69f4ed3126d4800244283a8ee30bc1be3c 100644 --- a/app/views/profiles/history.html.haml +++ b/app/views/profiles/history.html.haml @@ -1,3 +1,4 @@ +- page_title "History" %h3.page-title Your Account History %p.light diff --git a/app/views/profiles/keys/index.html.haml b/app/views/profiles/keys/index.html.haml index 0904c50c88b99e8fffa697fa317c30786cc2b474..e3af0d4e189fe9ddc7842d776bca031ce41faacb 100644 --- a/app/views/profiles/keys/index.html.haml +++ b/app/views/profiles/keys/index.html.haml @@ -1,3 +1,4 @@ +- page_title "SSH Keys" %h3.page-title SSH Keys Settings .pull-right diff --git a/app/views/profiles/keys/new.html.haml b/app/views/profiles/keys/new.html.haml index ccec716d0c66f02c9c6d86e6802251ea668a5740..2bf207a322161b7f2e2e5864a1083aee1e5a28ef 100644 --- a/app/views/profiles/keys/new.html.haml +++ b/app/views/profiles/keys/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Add SSH Keys" %h3.page-title Add an SSH Key %p.light Paste your public key here. Read more about how to generate a key on #{link_to "the SSH help page", help_page_path("ssh", "README")}. diff --git a/app/views/profiles/keys/show.html.haml b/app/views/profiles/keys/show.html.haml index cfd53298962f50c7b1fd064a3421568ad8084e3d..89f6f01581aa106d15dc61d083fdb527e7b6cb47 100644 --- a/app/views/profiles/keys/show.html.haml +++ b/app/views/profiles/keys/show.html.haml @@ -1 +1,2 @@ +- page_title @key.title, "SSH Keys" = render "key_details" diff --git a/app/views/profiles/notifications/show.html.haml b/app/views/profiles/notifications/show.html.haml index 273e72f8a4dfc26bf133cbc98afeee4c4107b6a0..a74d97dac3bb08bbf21db2505ed07e19724634c8 100644 --- a/app/views/profiles/notifications/show.html.haml +++ b/app/views/profiles/notifications/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Notifications" %h3.page-title Notifications Settings %p.light diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml index 4b04b113e89bd35066320a600811ad8a679210c3..21dabbdfe2cfc4e5318cf46f6bfa52c0a6552f13 100644 --- a/app/views/profiles/passwords/edit.html.haml +++ b/app/views/profiles/passwords/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Password" %h3.page-title Password Settings %p.light - if @user.password_automatically_set? diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml index 8bed6e0dbee1f4fcd1e21fd1c3a654a5402324e5..9c6204963e00fd81903fb8603cc55097cda3e012 100644 --- a/app/views/profiles/passwords/new.html.haml +++ b/app/views/profiles/passwords/new.html.haml @@ -1,3 +1,5 @@ +- page_title "New Password" +- header_title "New Password" %h3.page-title Setup new password %hr = form_for @user, url: profile_password_path, method: :post, html: { class: 'form-horizontal '} do |f| diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 6c745e69e4061fe83bd5a5393dc7bfc2ee57b93e..29c30905117df0b7e1ef163265b06af04df8b1fb 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Settings" %h3.page-title Profile Settings %p.light diff --git a/app/views/projects/_settings_nav.html.haml b/app/views/projects/_settings_nav.html.haml deleted file mode 100644 index f8b74809b76bdae7c42949fc4b4957ad5ebf41ab..0000000000000000000000000000000000000000 --- a/app/views/projects/_settings_nav.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -%ul.project-settings-nav.sidebar-subnav - = nav_link(path: 'projects#edit') do - = link_to edit_project_path(@project), title: 'Project', class: 'stat-tab tab', data: {placement: 'right'} do - = icon('pencil-square-o') - %span - Project - = nav_link(controller: [:project_members, :teams]) do - = link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab', data: {placement: 'right'} do - = icon('users') - %span - Members - = nav_link(controller: :deploy_keys) do - = link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys', data: {placement: 'right'} do - = icon('key') - %span - Deploy Keys - = nav_link(controller: :hooks) do - = link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Web Hooks', data: {placement: 'right'} do - = icon('link') - %span - Web Hooks - = nav_link(controller: :services) do - = link_to namespace_project_services_path(@project.namespace, @project), title: 'Services', data: {placement: 'right'} do - = icon('cogs') - %span - Services - = nav_link(controller: :protected_branches) do - = link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches', data: {placement: 'right'} do - = icon('lock') - %span - Protected branches diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index 89dd68d647185a0da034e66b57b89f5d389a0168..462f5b7afb09a8d608cbad67f86fbef8a6625118 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Blame", @blob.path, @ref %h3.page-title Blame view #tree-holder.tree-holder diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index 1f61a0b940c84b940e1517111b65e67180c8d889..e78181f880128de7c67700df7efd2674c0c75970 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @blob.path, @ref .file-editor %ul.nav.nav-tabs.js-edit-mode %li.active diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml index d78a01f6422ceed88b7dbdd057a297499adb1ff4..9b1d03b820ebba208f44024afb510ddbbbd347e0 100644 --- a/app/views/projects/blob/new.html.haml +++ b/app/views/projects/blob/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New File", @ref %h3.page-title New file .file-editor = form_tag(namespace_project_create_blob_path(@project.namespace, @project, @id), method: :post, class: 'form-horizontal form-new-file') do diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index 69167654c39d9fac445e6c80245c154fd1baa86f..a1d464bac59fcfb2d2bf40708f5ba65e3a52e874 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -1,3 +1,4 @@ +- page_title @blob.path, @ref %div.tree-ref-holder = render 'shared/ref_switcher', destination: 'blob', path: @path diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index a313ffcf27294a07dc1e6024d5c2ac2077d4f6f6..80acc9379083037cf997b181b9e1235dc4fd9048 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Branches" = render "projects/commits/head" %h3.page-title Branches diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index e5fcb98c68cb00d8f561619a77cfea206579c100..cac5dc91afd59b28d9e359e871e5d380a2144224 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Branch" - if @error .alert.alert-danger %button{ type: "button", class: "close", "data-dismiss" => "alert"} × diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index fc721067ed4d870da8deec7ea2466d67c089804e..fc91f71e8d2c1686bedec5ade14e3e84e2eb7478 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -1,3 +1,4 @@ +- page_title "#{@commit.title} (#{@commit.short_id})", "Commits" = render "commit_box" = render "projects/diffs/diffs", diffs: @diffs, project: @project = render "projects/notes/notes_with_form" diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index fb1012deb74a69c0d5bc1c4084a29e921af5fa78..c8531b090a6257aaa57795f3a9af0422aa25a7d5 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Commits", @ref = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml index 4745bfbeaaf061e5a1f896ed2864f0ac76b2be73..d1e579a2edeb82d2847c21c1e4bdfcddc4b81ad3 100644 --- a/app/views/projects/compare/index.html.haml +++ b/app/views/projects/compare/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Compare" = render "projects/commits/head" %h3.page-title diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 214b5bd337b5cb007189d1c4434f735609ad1cb6..3670dd5c13b81e8aa36b683de3dbe1bcb41bdee9 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -1,3 +1,4 @@ +- page_title "#{params[:from]}...#{params[:to]}" = render "projects/commits/head" %h3.page-title diff --git a/app/views/projects/deploy_keys/index.html.haml b/app/views/projects/deploy_keys/index.html.haml index 472a13a85242018cecb712a20c692fd00b23125c..2e9c5dc08c8f06d307aa8a18a3e0f6343b4f4026 100644 --- a/app/views/projects/deploy_keys/index.html.haml +++ b/app/views/projects/deploy_keys/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Deploy Keys" %h3.page-title Deploy keys allow read-only access to the repository diff --git a/app/views/projects/deploy_keys/new.html.haml b/app/views/projects/deploy_keys/new.html.haml index 186d6b58972f256ea8719302eb4f109e8a3748ca..01c810aee180b24f580f78f1833b4606590e9e1b 100644 --- a/app/views/projects/deploy_keys/new.html.haml +++ b/app/views/projects/deploy_keys/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Deploy Key" %h3.page-title New Deploy key %hr diff --git a/app/views/projects/deploy_keys/show.html.haml b/app/views/projects/deploy_keys/show.html.haml index 405b5bcd0d3a81e8a6f7da5c10866bafd4408b6f..7d44652af725ecd99aff497894de55e9bf43a7d6 100644 --- a/app/views/projects/deploy_keys/show.html.haml +++ b/app/views/projects/deploy_keys/show.html.haml @@ -1,3 +1,4 @@ +- page_title @key.title, "Deploy Keys" %h3.page-title Deploy key: = @key.title diff --git a/app/views/projects/forks/error.html.haml b/app/views/projects/forks/error.html.haml index 8eb4f795971939d0d5717b5e489e83593ea41a84..3d0ab5b85d674c95ae1f45695bb4ab72681808de 100644 --- a/app/views/projects/forks/error.html.haml +++ b/app/views/projects/forks/error.html.haml @@ -1,3 +1,4 @@ +- page_title "Fork project" - if @forked_project && !@forked_project.saved? .alert.alert-danger.alert-block %h4 diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml index 5a6c46f320885bd11a5d489780f52cc702450756..b7a2ed68e256c2675971cdd52a44c986fa48bb92 100644 --- a/app/views/projects/forks/new.html.haml +++ b/app/views/projects/forks/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Fork project" %h3.page-title Fork project %p.lead Click to fork the project to a user or group diff --git a/app/views/projects/graphs/commits.html.haml b/app/views/projects/graphs/commits.html.haml index 78b4c1923dd4669f09be01b43727a22ef01c8e69..254a76e108baecbf4cd96093d4bfc05515c579fa 100644 --- a/app/views/projects/graphs/commits.html.haml +++ b/app/views/projects/graphs/commits.html.haml @@ -1,3 +1,4 @@ +- page_title "Commit statistics" = render 'head' %p.lead diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index e3d5094ddc5fb6bf41774a02741bfdf80de69f14..3a8dc89f84cc3c25b8dbf90f2eeeaf33a645a416 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Contributor statistics" = render 'head' .loading-graph .center diff --git a/app/views/projects/hooks/index.html.haml b/app/views/projects/hooks/index.html.haml index bbaddba31b9ee4bc0a2094317fa4cf8bf701e24e..808c03148f41ceb51c43949bf7cfd83c6f0fbc60 100644 --- a/app/views/projects/hooks/index.html.haml +++ b/app/views/projects/hooks/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Web Hooks" %h3.page-title Web hooks diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml index 934b6b8c017212afeb9664e0c5d7ea931463ba1b..f8f2e192e291f20a8960862def746e375953f2c4 100644 --- a/app/views/projects/imports/new.html.haml +++ b/app/views/projects/imports/new.html.haml @@ -1,3 +1,4 @@ +- page_title "Import repository" %h3.page-title - if @project.import_failed? Import failed. Retry? diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml index 2d1fdafed24d31497feb9ac9dede513d38c9fbdf..39fe0fc1c4f754e2225f590d0503134bda0203ab 100644 --- a/app/views/projects/imports/show.html.haml +++ b/app/views/projects/imports/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Import in progress" .save-project-loader .center %h2 diff --git a/app/views/projects/issues/edit.html.haml b/app/views/projects/issues/edit.html.haml index b1bc3ba0eba684a146b503fa89225bda4614e840..53b6f0879c9c568b87be742dd59e869714ec285c 100644 --- a/app/views/projects/issues/edit.html.haml +++ b/app/views/projects/issues/edit.html.haml @@ -1 +1,2 @@ +- page_title "Edit", "#{@issue.title} (##{@issue.iid})", "Issues" = render "form" diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index c2522816f3b1f808dbb02338a2767b6507b9bca9..709ea1f789739e114d07a036ff9166502d865e3a 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Issues" = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_issues_url(@project.namespace, @project, :atom, private_token: current_user.private_token), title: "#{@project.name} issues") diff --git a/app/views/projects/issues/new.html.haml b/app/views/projects/issues/new.html.haml index b1bc3ba0eba684a146b503fa89225bda4614e840..da6edd5c2d2fd1b4d4859efc4ed3ed0531fe0038 100644 --- a/app/views/projects/issues/new.html.haml +++ b/app/views/projects/issues/new.html.haml @@ -1 +1,2 @@ +- page_title "New Issue" = render "form" diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index bd28d8a1db29a82f6f1cde6a54d7300a21606ebc..81478dfe568093268409b54d3e5d15d8ab589526 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -1,3 +1,4 @@ +- page_title "#{@issue.title} (##{@issue.iid})", "Issues" .issue .issue-details %h4.page-title diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml index e003d1dfe7f586ffffed167502e51f428ddbb9be..645402667fd8f80613e5333fe2f63ef64a9afd3a 100644 --- a/app/views/projects/labels/edit.html.haml +++ b/app/views/projects/labels/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @label.name, "Labels" %h3 Edit label %span.light #{@label.name} diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 0700e72d39c8e659a4195a009552d6e0383c28df..7d19415a7f4c55122a63211f00db8beae6ebc3a8 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Labels" - if can? current_user, :admin_label, @project = link_to new_namespace_project_label_path(@project.namespace, @project), class: "pull-right btn btn-new" do New label diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml index 0683ed5d4fbcf6ae9f5b0cfb3e783cc7c6084654..b3ef17025c30617da25c4502150dca9969846070 100644 --- a/app/views/projects/labels/new.html.haml +++ b/app/views/projects/labels/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Label" %h3 New label .back-link = link_to namespace_project_labels_path(@project.namespace, @project) do diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index 45dd410dd152cbef588dcdbac51ef862cd8a3086..c2f5cdacae74d4ecc33f98c85b9b0f2a530cede1 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -1,3 +1,4 @@ +- page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" .merge-request{'data-url' => merge_request_path(@merge_request)} .merge-request-details = render "projects/merge_requests/show/mr_title" diff --git a/app/views/projects/merge_requests/edit.html.haml b/app/views/projects/merge_requests/edit.html.haml index 839c63986ab36a155125e67a5739f0702dd8ef6e..7e5cb07f249543eda2a5b6ce49048e01841a1039 100644 --- a/app/views/projects/merge_requests/edit.html.haml +++ b/app/views/projects/merge_requests/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" %h3.page-title = "Edit merge request ##{@merge_request.iid}" %hr diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index d7992bdd19ea8a0412d94cebcaa28598514c83ff..ab845a7e719bf3d9a418ee555dd822fcc9def6a1 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Merge Requests" .append-bottom-10 .pull-right = render 'shared/issuable_search_form', path: namespace_project_merge_requests_path(@project.namespace, @project) diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml index b9c466657de4f01fe66edf0f9f530e8664dfc9db..15bd4e2fafd1cdfd188ca278cf9c00fa455cec77 100644 --- a/app/views/projects/merge_requests/invalid.html.haml +++ b/app/views/projects/merge_requests/invalid.html.haml @@ -1,3 +1,4 @@ +- page_title "#{@merge_request.title} (##{@merge_request.iid})", "Merge Requests" .merge-request = render "projects/merge_requests/show/mr_title" = render "projects/merge_requests/show/mr_box" diff --git a/app/views/projects/merge_requests/new.html.haml b/app/views/projects/merge_requests/new.html.haml index 4756903d0e00465a47b0bcdd5cfa93cd0a4414c9..b038a640f67d31da7c95339229924c70f03c6b8b 100644 --- a/app/views/projects/merge_requests/new.html.haml +++ b/app/views/projects/merge_requests/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Merge Request" - if @merge_request.can_be_created = render 'new_submit' - else diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml index b1bc3ba0eba684a146b503fa89225bda4614e840..c09815a212a35ff914f6265d4ac1df054b52cffa 100644 --- a/app/views/projects/milestones/edit.html.haml +++ b/app/views/projects/milestones/edit.html.haml @@ -1 +1,2 @@ +- page_title "Edit", @milestone.title, "Milestones" = render "form" diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index d3eab8d6d7509d19cb1bba0bda2959999fc5974c..995eecd783014f9927e8571ff1be7c0179ed09e0 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Milestones" .pull-right - if can? current_user, :admin_milestone, @project = link_to new_namespace_project_milestone_path(@project.namespace, @project), class: "pull-right btn btn-new", title: "New Milestone" do diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml index b1bc3ba0eba684a146b503fa89225bda4614e840..47149dfea41e88fcf0bcedad646c79c477d0bf56 100644 --- a/app/views/projects/milestones/new.html.haml +++ b/app/views/projects/milestones/new.html.haml @@ -1 +1,2 @@ +- page_title "New Milestone" = render "form" diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 25cc00309658282dd2b31ce9c5942676f76fdd60..bba2b8764acf19a9aff0569ce9efc41ba1411743 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -1,3 +1,4 @@ +- page_title @milestone.title, "Milestones" %h4.page-title .issue-box{ class: issue_box_class(@milestone) } - if @milestone.closed? diff --git a/app/views/projects/network/show.html.haml b/app/views/projects/network/show.html.haml index c36bad1e94b6096af8c2e0b0b056aec3e330a6d2..c67a7d256a84b04bcd97ef4312c0ff81a5825fae 100644 --- a/app/views/projects/network/show.html.haml +++ b/app/views/projects/network/show.html.haml @@ -1,3 +1,4 @@ +- page_title "Network", @ref = render "head" .project-network .controls diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 47c69f89a97888c6ee3dde97a3977c9e868de584..e56d8615132f256c4ddd806b06d6bea6d7c12e64 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -1,3 +1,5 @@ +- page_title 'New Project' +- header_title 'New Project' .project-edit-container .project-edit-errors = render 'projects/errors' diff --git a/app/views/projects/project_members/import.html.haml b/app/views/projects/project_members/import.html.haml index 293754cd0c0fa180a5f80dec6fdb78738d88306a..6914543f6dad300463d906d86e7a11b3b661f4b6 100644 --- a/app/views/projects/project_members/import.html.haml +++ b/app/views/projects/project_members/import.html.haml @@ -1,3 +1,4 @@ +- page_title "Import members" %h3.page-title Import members from another project %p.light diff --git a/app/views/projects/project_members/index.html.haml b/app/views/projects/project_members/index.html.haml index 36a6f6a15547d9d05737d5ff08f475a198531dae..6edb92acd4d5eb983733b23117bc5ac274c78c26 100644 --- a/app/views/projects/project_members/index.html.haml +++ b/app/views/projects/project_members/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Members" %h3.page-title Users with access to this project diff --git a/app/views/projects/protected_branches/index.html.haml b/app/views/projects/protected_branches/index.html.haml index a3464c0e5e183d623abb99c5372b588349c9aee3..52b3a50c1e61f41913f11fc15d0f44be6a5d28b9 100644 --- a/app/views/projects/protected_branches/index.html.haml +++ b/app/views/projects/protected_branches/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Protected branches" %h3.page-title Protected branches %p.light Keep stable branches secure and force developers to use Merge Requests %hr diff --git a/app/views/projects/services/edit.html.haml b/app/views/projects/services/edit.html.haml index bcc5832792fea10b70d29a9fb15633f06e001dd0..50ed78286d2d6cd2c466c79964d36f8ce1afc661 100644 --- a/app/views/projects/services/edit.html.haml +++ b/app/views/projects/services/edit.html.haml @@ -1 +1,2 @@ +- page_title @service.title, "Services" = render 'form' diff --git a/app/views/projects/services/index.html.haml b/app/views/projects/services/index.html.haml index 0d3ccb6bb839e7306e5b9409fee7e309d11eea3e..1065def693bbbecf3a8846b054a6735f9cda7d9a 100644 --- a/app/views/projects/services/index.html.haml +++ b/app/views/projects/services/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Services" %h3.page-title Project services %p.light Project services allow you to integrate GitLab with other applications diff --git a/app/views/projects/snippets/edit.html.haml b/app/views/projects/snippets/edit.html.haml index 7baddebde455944aebc557848ab5f25409b2ef87..945f0084dff1da7d823a00ffe6e17e4e08d34189 100644 --- a/app/views/projects/snippets/edit.html.haml +++ b/app/views/projects/snippets/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @snippet.title, "Snippets" %h3.page-title Edit snippet %hr diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml index e2d8ec673a17fe3f2e6ced456fbf3d9b5da3ba22..da9401bd8c1625a3308629ddd4afbd9251dcf3fd 100644 --- a/app/views/projects/snippets/index.html.haml +++ b/app/views/projects/snippets/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Snippets" %h3.page-title Snippets - if can? current_user, :write_project_snippet, @project diff --git a/app/views/projects/snippets/new.html.haml b/app/views/projects/snippets/new.html.haml index 5efe662665ee72824a0ef2e9d8904161491cfe51..e38d95c45e7e893c5f88feee5d43ec04ddadf9c8 100644 --- a/app/views/projects/snippets/new.html.haml +++ b/app/views/projects/snippets/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Snippets" %h3.page-title New snippet %hr diff --git a/app/views/projects/snippets/show.html.haml b/app/views/projects/snippets/show.html.haml index d19689a1056213a16988e15c975c09e4c2e4d888..5725d804df3f7a18b57d10bb176c1a6904ed7b37 100644 --- a/app/views/projects/snippets/show.html.haml +++ b/app/views/projects/snippets/show.html.haml @@ -1,3 +1,4 @@ +- page_title @snippet.title, "Snippets" %h3.page-title = @snippet.title diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index f1bc2bc9a2b23aa8cfc5526a610b7b4c59bb0c6f..d4652a47cbae1f5ab0b2357afe362e9132c45402 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Tags" = render "projects/commits/head" %h3.page-title diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index 655044438d50a412085d3e9e2ee351fefebb8ccb..172fafdeeff41a87f7acd4e6ac3206c54412031d 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Tag" - if @error .alert.alert-danger %button{ type: "button", class: "close", "data-dismiss" => "alert"} × diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index a8a580944e1d7c0fea60a60f3413141463c107e6..72916cad182995dcd1f7f9db137aae68ea99c8cf 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -1,3 +1,4 @@ +- page_title @path.presence || "Files", @ref = content_for :meta_tags do - if current_user = auto_discovery_link_tag(:atom, namespace_project_commits_url(@project.namespace, @project, @ref, format: :atom, private_token: current_user.private_token), title: "#{@project.name}:#{@ref} commits") diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml index 566850cb78d3487b10593cc71ae2aa8e41c3d203..3f1dce1050c1d46975f0e1a402bef6b0b7e328d8 100644 --- a/app/views/projects/wikis/edit.html.haml +++ b/app/views/projects/wikis/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @page.title, "Wiki" = render 'nav' .pull-right = render 'main_links' diff --git a/app/views/projects/wikis/empty.html.haml b/app/views/projects/wikis/empty.html.haml index 48058124f97fc28154ae2f46ea4b6fdb4a258c8e..ead99412406d6fda74ea213cb9867d5463779b0d 100644 --- a/app/views/projects/wikis/empty.html.haml +++ b/app/views/projects/wikis/empty.html.haml @@ -1,3 +1,4 @@ +- page_title "Wiki" %h3.page-title Empty page %hr .error_message diff --git a/app/views/projects/wikis/git_access.html.haml b/app/views/projects/wikis/git_access.html.haml index 365edb524f43b97124a5f948001958f09a306809..825f2a161c42eb52a3161346dd5d166283fe0e41 100644 --- a/app/views/projects/wikis/git_access.html.haml +++ b/app/views/projects/wikis/git_access.html.haml @@ -1,3 +1,4 @@ +- page_title "Git Access", "Wiki" = render 'nav' .row .col-sm-6 diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml index 91291f753f772e66b579fa0c97cecfcfb8a69aab..673ec2d20e5d415fea7d0f53f139fc322f74a40c 100644 --- a/app/views/projects/wikis/history.html.haml +++ b/app/views/projects/wikis/history.html.haml @@ -1,3 +1,4 @@ +- page_title "History", @page.title, "Wiki" = render 'nav' %h3.page-title %span.light History for diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml index ee233d9086f99d02406169cf9881d7dec7cd40ba..890ff1aed738c64d044b6177591c2175d38914cb 100644 --- a/app/views/projects/wikis/pages.html.haml +++ b/app/views/projects/wikis/pages.html.haml @@ -1,3 +1,4 @@ +- page_title "All Pages", "Wiki" = render 'nav' %h3.page-title All Pages diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml index a6263e93f678e515a11429df7755a25772b0af66..83cd4c66672ddb62b268db19224e201da8b638ea 100644 --- a/app/views/projects/wikis/show.html.haml +++ b/app/views/projects/wikis/show.html.haml @@ -1,3 +1,4 @@ +- page_title @page.title, "Wiki" = render 'nav' %h3.page-title = @page.title diff --git a/app/views/search/show.html.haml b/app/views/search/show.html.haml index e9f2711be2a8df93d7aebafabe838e2a60586e91..60f9e9ac9de07b3a20ab866f96f83d9066fe097c 100644 --- a/app/views/search/show.html.haml +++ b/app/views/search/show.html.haml @@ -1,3 +1,4 @@ +- page_title @search_term = render 'search/form' %hr - if @search_term diff --git a/app/views/snippets/current_user_index.html.haml b/app/views/snippets/current_user_index.html.haml index 6bb2237a759c5eedbbf1c7d5e423cfc046ee8508..0718f743828651fea87fe43f0b6ba40d526c4447 100644 --- a/app/views/snippets/current_user_index.html.haml +++ b/app/views/snippets/current_user_index.html.haml @@ -1,3 +1,4 @@ +- page_title "Your Snippets" %h3.page-title Your Snippets .pull-right diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml index 30aa174edfb3329b039c4da52dabf4982ba9e4c9..1a380035661d4a24ca894e70734c13b8f8f7d096 100644 --- a/app/views/snippets/edit.html.haml +++ b/app/views/snippets/edit.html.haml @@ -1,3 +1,4 @@ +- page_title "Edit", @snippet.title, "Snippets" %h3.page-title Edit snippet %hr diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml index 108dd0cca3ef5811d4e3ea66e982789b98f7cd7c..e9bb6a908d3db508c55534dc617c3743d7afde30 100644 --- a/app/views/snippets/index.html.haml +++ b/app/views/snippets/index.html.haml @@ -1,3 +1,4 @@ +- page_title "Public Snippets" %h3.page-title Public snippets diff --git a/app/views/snippets/new.html.haml b/app/views/snippets/new.html.haml index 77cfd9af335ab8afde5915e4ecc64a130d547e35..a74d5e792ad428866f6125b6fcd8190b86a22a4e 100644 --- a/app/views/snippets/new.html.haml +++ b/app/views/snippets/new.html.haml @@ -1,3 +1,4 @@ +- page_title "New Snippet" %h3.page-title New snippet %hr diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index 5204fb9a90702aca1d752f00e5567ca60c94a7f9..70a95abde6f2be3dfd9a6f068a85949637ef61d1 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -1,3 +1,4 @@ +- page_title @snippet.title, "Snippets" %h3.page-title = @snippet.title diff --git a/app/views/snippets/user_index.html.haml b/app/views/snippets/user_index.html.haml index df524cd18b0cb46b01612a3c6976605dccc336ba..23700eb39dafc6910859ddefac764f4734edd733 100644 --- a/app/views/snippets/user_index.html.haml +++ b/app/views/snippets/user_index.html.haml @@ -1,3 +1,4 @@ +- page_title "Snippets", @user.name %h3.page-title = image_tag avatar_icon(@user.email), class: "avatar s24" = @user.name diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 0576c6a11b9c26d753e79eb3c34aed79d61d43c2..6ed45fedfa2d431b8825e6aeb56b401a060e2954 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -1,3 +1,6 @@ +- page_title @user.name +- header_title @user.name, user_path(@user) + = content_for :meta_tags do = auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity") diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 9dce495106f50cd4167eb3c4e4aa941aad6f8f66..8f8c41697406fb8ea0a3071095efbc828b359b43 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -2,13 +2,8 @@ # four configuration values can also be set straight in your models. Devise.setup do |config| # ==> Mailer Configuration - # Configure the e-mail address which will be shown in Devise::Mailer, - # note that it will be overwritten if you use your own mailer class with default "from" parameter. - config.mailer_sender = "GitLab <#{Gitlab.config.gitlab.email_from}>" - - # Configure the class responsible to send e-mails. - # config.mailer = "Devise::Mailer" + config.mailer = "DeviseMailer" # ==> ORM configuration # Load and configure the ORM. Supports :active_record (default) and diff --git a/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000000000000000000000000000000000000..4ca676f6c72908f3281ad3e64f5efb5bf8a93bb9 --- /dev/null +++ b/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb @@ -0,0 +1,20 @@ +# This migration comes from acts_as_taggable_on_engine (originally 2) +class AddMissingUniqueIndices < ActiveRecord::Migration + def self.up + add_index :tags, :name, unique: true + + remove_index :taggings, :tag_id + remove_index :taggings, [:taggable_id, :taggable_type, :context] + add_index :taggings, + [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type], + unique: true, name: 'taggings_idx' + end + + def self.down + remove_index :tags, :name + + remove_index :taggings, name: 'taggings_idx' + add_index :taggings, :tag_id + add_index :taggings, [:taggable_id, :taggable_type, :context] + end +end diff --git a/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000000000000000000000000000000000000..8edb508078131059ac506257527d5dc02bad67be --- /dev/null +++ b/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb @@ -0,0 +1,15 @@ +# This migration comes from acts_as_taggable_on_engine (originally 3) +class AddTaggingsCounterCacheToTags < ActiveRecord::Migration + def self.up + add_column :tags, :taggings_count, :integer, default: 0 + + ActsAsTaggableOn::Tag.reset_column_information + ActsAsTaggableOn::Tag.find_each do |tag| + ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) + end + end + + def self.down + remove_column :tags, :taggings_count + end +end diff --git a/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000000000000000000000000000000000000..71f2d7f43309d0628ec0120e211c945559c46846 --- /dev/null +++ b/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb @@ -0,0 +1,10 @@ +# This migration comes from acts_as_taggable_on_engine (originally 4) +class AddMissingTaggableIndex < ActiveRecord::Migration + def self.up + add_index :taggings, [:taggable_id, :taggable_type, :context] + end + + def self.down + remove_index :taggings, [:taggable_id, :taggable_type, :context] + end +end diff --git a/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb new file mode 100644 index 0000000000000000000000000000000000000000..bfb06bc7cda48c12580961fc53373a6153ac7f68 --- /dev/null +++ b/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb @@ -0,0 +1,10 @@ +# This migration comes from acts_as_taggable_on_engine (originally 5) +# This migration is added to circumvent issue #623 and have special characters +# work properly +class ChangeCollationForTagNames < ActiveRecord::Migration + def up + if ActsAsTaggableOn::Utils.using_mysql? + execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;") + end + end +end diff --git a/db/schema.rb b/db/schema.rb index a2ed9efc93362b8f183434f49dd940d6a2fb93b8..02882186fc85814cd04fcc19672c6a2de229a7ca 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -433,13 +433,16 @@ ActiveRecord::Schema.define(version: 20150429002313) do t.datetime "created_at" end - add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree + add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree create_table "tags", force: true do |t| - t.string "name" + t.string "name" + t.integer "taggings_count", default: 0 end + add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree + create_table "users", force: true do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false diff --git a/doc/api/README.md b/doc/api/README.md index dec530d0b812022be099d3023f279de0b3e850dc..f6757b0a6aa30083eb5212f39547882782ba4f99 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -6,6 +6,7 @@ - [Session](session.md) - [Projects](projects.md) - [Project Snippets](project_snippets.md) +- [Services](services.md) - [Repositories](repositories.md) - [Repository Files](repository_files.md) - [Commits](commits.md) diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md index e32984c4e68f2fbcf1893740e505b7f3638d112a..2cca46c86a3c06ea916cd6891f8f9b487a093574 100644 --- a/doc/update/upgrader.md +++ b/doc/update/upgrader.md @@ -27,10 +27,10 @@ If you have local changes to your GitLab repository the script will stash them a Note: GitLab 7.9 adds `nodejs` as a dependency. GitLab 7.6 adds `libkrb5-dev` as a dependency (installed by default on Ubuntu and OSX). GitLab 7.2 adds `pkg-config` and `cmake` as dependency. Please check the dependencies in the [installation guide.](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md#1-packages-dependencies) cd /home/git/gitlab - sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.0"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' + sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.1"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' # to perform a non-interactive install (no user input required) you can add -y - # sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.0"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y + # sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.1"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y ## 3. Start application @@ -65,7 +65,7 @@ Here is a one line command with step 1 to 5 for the next time you upgrade: cd /home/git/gitlab; \ sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \ sudo service gitlab stop; \ - sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.0"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y; \ + sudo -u git -H ruby -Ilib -e 'require "gitlab/upgrader"' -e 'class Gitlab::Upgrader' -e 'def latest_version_raw' -e '"v7.10.1"' -e 'end' -e 'end' -e 'Gitlab::Upgrader.new.execute' -- -y; \ cd /home/git/gitlab-shell; \ sudo -u git -H git fetch; \ sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`; \ diff --git a/features/project/project.feature b/features/project/project.feature index 3e1fd54bee84ca92fcbb4cd61880287715e6e0b4..ae28312a69ac09576defd9d0a1f0c5fde3c078fb 100644 --- a/features/project/project.feature +++ b/features/project/project.feature @@ -55,3 +55,10 @@ Feature: Project Then I should see project "Forum" README And I visit project "Shop" page Then I should see project "Shop" README + + Scenario: I tag a project + When I visit edit project "Shop" page + Then I should see project settings + And I add project tags + And I save project + Then I should see project tags diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb index d39c8e7d2db82d10935ce52e5b06aa716c080db0..f14396bcfffc7374f950e844589a68f6e01222f4 100644 --- a/features/steps/project/project.rb +++ b/features/steps/project/project.rb @@ -94,4 +94,12 @@ class Spinach::Features::Project < Spinach::FeatureSteps page.should have_link 'README.md' page.should have_content 'testme' end + + step 'I add project tags' do + fill_in 'Tags', with: 'tag1, tag2' + end + + step 'I should see project tags' do + expect(find_field('Tags').value).to eq 'tag1, tag2' + end end diff --git a/features/steps/shared/markdown.rb b/features/steps/shared/markdown.rb index e71700880cde96622a3a307ad47e79deaba25e80..a7231c47d14306829efc0653454a4fa46728d601 100644 --- a/features/steps/shared/markdown.rb +++ b/features/steps/shared/markdown.rb @@ -2,8 +2,12 @@ module SharedMarkdown include Spinach::DSL def header_should_have_correct_id_and_link(level, text, id, parent = ".wiki") - find(:css, "#{parent} h#{level}##{id}").text.should == text - find(:css, "#{parent} h#{level}##{id} > :last-child")[:href].should =~ /##{id}$/ + node = find("#{parent} h#{level} a##{id}") + node[:href].should == "##{id}" + + # Work around a weird Capybara behavior where calling `parent` on a node + # returns the whole document, not the node's actual parent element + find(:xpath, "#{node.path}/..").text.should == text end def create_taskable(type, title) diff --git a/lib/gitlab/google_code_import/client.rb b/lib/gitlab/google_code_import/client.rb index 02f31e45f885f8b753610eac2bec2e786286c227..890bd9a35541e1fff14c728957ec9ade908ad2a1 100644 --- a/lib/gitlab/google_code_import/client.rb +++ b/lib/gitlab/google_code_import/client.rb @@ -21,6 +21,10 @@ module Gitlab @repos ||= raw_data["projects"].map { |raw_repo| GoogleCodeImport::Repository.new(raw_repo) }.select(&:git?) end + def incompatible_repos + @incompatible_repos ||= raw_data["projects"].map { |raw_repo| GoogleCodeImport::Repository.new(raw_repo) }.reject(&:git?) + end + def repo(id) repos.find { |repo| repo.id == id } end diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 44779d7fdd82c746c476668f2934c49a39f55f19..8348e28d0f51b92b4bc6fc5abe1a5fc27c5cb779 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -3,33 +3,10 @@ require 'html/pipeline' module Gitlab # Custom parser for GitLab-flavored Markdown # - # It replaces references in the text with links to the appropriate items in - # GitLab. - # - # Supported reference formats are: - # * @foo for team members - # * #123 for issues - # * JIRA-123 for Jira issues - # * !123 for merge requests - # * $123 for snippets - # * 1c002d for specific commit - # * 1c002d...35cfb2 for commit ranges (comparisons) - # - # It also parses Emoji codes to insert images. See - # http://www.emoji-cheat-sheet.com/ for a list of the supported icons. - # - # Examples - # - # >> gfm("Hey @david, can you fix this?") - # => "Hey <a href="/u/david">@david</a>, can you fix this?" - # - # >> gfm("Commit 35d5f7c closes #1234") - # => "Commit <a href="/gitlab/commits/35d5f7c">35d5f7c</a> closes <a href="/gitlab/issues/1234">#1234</a>" - # - # >> gfm(":trollface:") - # => "<img alt=\":trollface:\" class=\"emoji\" src=\"/images/trollface.png" title=\":trollface:\" /> + # See the files in `lib/gitlab/markdown/` for specific processing information. module Markdown # Provide autoload paths for filters to prevent a circular dependency error + autoload :AutolinkFilter, 'gitlab/markdown/autolink_filter' autoload :CommitRangeReferenceFilter, 'gitlab/markdown/commit_range_reference_filter' autoload :CommitReferenceFilter, 'gitlab/markdown/commit_reference_filter' autoload :EmojiFilter, 'gitlab/markdown/emoji_filter' @@ -37,7 +14,9 @@ module Gitlab autoload :IssueReferenceFilter, 'gitlab/markdown/issue_reference_filter' autoload :LabelReferenceFilter, 'gitlab/markdown/label_reference_filter' autoload :MergeRequestReferenceFilter, 'gitlab/markdown/merge_request_reference_filter' + autoload :SanitizationFilter, 'gitlab/markdown/sanitization_filter' autoload :SnippetReferenceFilter, 'gitlab/markdown/snippet_reference_filter' + autoload :TableOfContentsFilter, 'gitlab/markdown/table_of_contents_filter' autoload :UserReferenceFilter, 'gitlab/markdown/user_reference_filter' # Public: Parse the provided text with GitLab-Flavored Markdown @@ -74,13 +53,13 @@ module Gitlab pipeline = HTML::Pipeline.new(filters) context = { - # SanitizationFilter - whitelist: sanitization_whitelist, - # EmojiFilter asset_root: Gitlab.config.gitlab.url, asset_host: Gitlab::Application.config.asset_host, + # TableOfContentsFilter + no_header_anchors: options[:no_header_anchors], + # ReferenceFilter current_user: current_user, only_path: options[:reference_only_path], @@ -111,12 +90,14 @@ module Gitlab # SanitizationFilter should come first so that all generated reference HTML # goes through untouched. # - # See https://gitlab.com/gitlab-org/html-pipeline-gitlab for more filters + # See https://github.com/jch/html-pipeline#filters for more filters. def filters [ - HTML::Pipeline::SanitizationFilter, + Gitlab::Markdown::SanitizationFilter, Gitlab::Markdown::EmojiFilter, + Gitlab::Markdown::TableOfContentsFilter, + Gitlab::Markdown::AutolinkFilter, Gitlab::Markdown::UserReferenceFilter, Gitlab::Markdown::IssueReferenceFilter, @@ -125,36 +106,10 @@ module Gitlab Gitlab::Markdown::SnippetReferenceFilter, Gitlab::Markdown::CommitRangeReferenceFilter, Gitlab::Markdown::CommitReferenceFilter, - Gitlab::Markdown::LabelReferenceFilter, + Gitlab::Markdown::LabelReferenceFilter ] end - # Customize the SanitizationFilter whitelist - # - # - Allow `class` and `id` attributes on all elements - # - Allow `span` elements - # - Remove `rel` attributes from `a` elements - # - Remove `a` nodes with `javascript:` in the `href` attribute - def sanitization_whitelist - whitelist = HTML::Pipeline::SanitizationFilter::WHITELIST - whitelist[:attributes][:all].push('class', 'id') - whitelist[:elements].push('span') - - fix_anchors = lambda do |env| - name, node = env[:node_name], env[:node] - if name == 'a' - node.remove_attribute('rel') - if node['href'] && node['href'].match('javascript:') - node.remove_attribute('href') - end - end - end - - whitelist[:transformers].push(fix_anchors) - - whitelist - end - # Turn list items that start with "[ ]" into HTML checkbox inputs. def parse_tasks(text) li_tag = '<li class="task-list-item">' diff --git a/lib/gitlab/markdown/autolink_filter.rb b/lib/gitlab/markdown/autolink_filter.rb new file mode 100644 index 0000000000000000000000000000000000000000..4e14a048cfb3dc96e3cb9c4ca7024b1347499de3 --- /dev/null +++ b/lib/gitlab/markdown/autolink_filter.rb @@ -0,0 +1,100 @@ +require 'html/pipeline/filter' +require 'uri' + +module Gitlab + module Markdown + # HTML Filter for auto-linking URLs in HTML. + # + # Based on HTML::Pipeline::AutolinkFilter + # + # Context options: + # :autolink - Boolean, skips all processing done by this filter when false + # :link_attr - Hash of attributes for the generated links + # + class AutolinkFilter < HTML::Pipeline::Filter + include ActionView::Helpers::TagHelper + + # Pattern to match text that should be autolinked. + # + # A URI scheme begins with a letter and may contain letters, numbers, + # plus, period and hyphen. Schemes are case-insensitive but we're being + # picky here and allowing only lowercase for autolinks. + # + # See http://en.wikipedia.org/wiki/URI_scheme + # + # The negative lookbehind ensures that users can paste a URL followed by a + # period or comma for punctuation without those characters being included + # in the generated link. + # + # Rubular: http://rubular.com/r/cxjPyZc7Sb + LINK_PATTERN = %r{([a-z][a-z0-9\+\.-]+://\S+)(?<!,|\.)} + + # Text matching LINK_PATTERN inside these elements will not be linked + IGNORE_PARENTS = %w(a code kbd pre script style).to_set + + def call + return doc if context[:autolink] == false + + rinku_parse + text_parse + end + + private + + # Run the text through Rinku as a first pass + # + # This will quickly autolink http(s) and ftp links. + # + # `@doc` will be re-parsed with the HTML String from Rinku. + def rinku_parse + # Convert the options from a Hash to a String that Rinku expects + options = tag_options(link_options) + + # NOTE: We don't parse email links because it will erroneously match + # external Commit and CommitRange references. + # + # The final argument tells Rinku to link short URLs that don't include a + # period (e.g., http://localhost:3000/) + rinku = Rinku.auto_link(html, :urls, options, IGNORE_PARENTS.to_a, 1) + + # Rinku returns a String, so parse it back to a Nokogiri::XML::Document + # for further processing. + @doc = parse_html(rinku) + end + + # Autolinks any text matching LINK_PATTERN that Rinku didn't already + # replace + def text_parse + search_text_nodes(doc).each do |node| + content = node.to_html + + next if has_ancestor?(node, IGNORE_PARENTS) + next unless content.match(LINK_PATTERN) + + # If Rinku didn't link this, there's probably a good reason, so we'll + # skip it too + next if content.start_with?(*%w(http https ftp)) + + html = autolink_filter(content) + + next if html == content + + node.replace(html) + end + + doc + end + + def autolink_filter(text) + text.gsub(LINK_PATTERN) do |match| + options = link_options.merge(href: match) + content_tag(:a, match, options) + end + end + + def link_options + @link_options ||= context[:link_attr] || {} + end + end + end +end diff --git a/lib/gitlab/markdown/issue_reference_filter.rb b/lib/gitlab/markdown/issue_reference_filter.rb index 4b360369d3768f5905c05fd41aa9b275e9706f6f..1e885615163092b9756417e544bad8af59ee8ea5 100644 --- a/lib/gitlab/markdown/issue_reference_filter.rb +++ b/lib/gitlab/markdown/issue_reference_filter.rb @@ -44,21 +44,20 @@ module Gitlab # Returns a String with `#123` references replaced with links. All links # have `gfm` and `gfm-issue` class names attached for styling. def issue_link_filter(text) - self.class.references_in(text) do |match, issue, project_ref| + self.class.references_in(text) do |match, id, project_ref| project = self.project_from_ref(project_ref) - if project && project.issue_exists?(issue) - # FIXME (rspeicher): Law of Demeter - push_result(:issue, project.issues.where(iid: issue).first) + if project && issue = project.get_issue(id) + push_result(:issue, issue) - url = url_for_issue(issue, project, only_path: context[:only_path]) + url = url_for_issue(id, project, only_path: context[:only_path]) - title = escape_once("Issue: #{title_for_issue(issue, project)}") + title = escape_once("Issue: #{issue.title}") klass = reference_class(:issue) %(<a href="#{url}" title="#{title}" - class="#{klass}">#{project_ref}##{issue}</a>) + class="#{klass}">#{project_ref}##{id}</a>) else match end @@ -68,10 +67,6 @@ module Gitlab def url_for_issue(*args) IssuesHelper.url_for_issue(*args) end - - def title_for_issue(*args) - IssuesHelper.title_for_issue(*args) - end end end end diff --git a/lib/gitlab/markdown/merge_request_reference_filter.rb b/lib/gitlab/markdown/merge_request_reference_filter.rb index 7c28fe112efcd0b3a8cb3bf9c811b7bb6e1ec50a..740d72abb3699025c6cdaf25fbb01c5764784d60 100644 --- a/lib/gitlab/markdown/merge_request_reference_filter.rb +++ b/lib/gitlab/markdown/merge_request_reference_filter.rb @@ -64,7 +64,6 @@ module Gitlab end end - # TODO (rspeicher): Cleanup def url_for_merge_request(mr, project) h = Rails.application.routes.url_helpers h.namespace_project_merge_request_url(project.namespace, project, mr, diff --git a/lib/gitlab/markdown/sanitization_filter.rb b/lib/gitlab/markdown/sanitization_filter.rb new file mode 100644 index 0000000000000000000000000000000000000000..9a154e0b2feb08447b1e5bd462e61c7d8d8d95d2 --- /dev/null +++ b/lib/gitlab/markdown/sanitization_filter.rb @@ -0,0 +1,38 @@ +require 'html/pipeline/filter' +require 'html/pipeline/sanitization_filter' + +module Gitlab + module Markdown + # Sanitize HTML + # + # Extends HTML::Pipeline::SanitizationFilter with a custom whitelist. + class SanitizationFilter < HTML::Pipeline::SanitizationFilter + def whitelist + whitelist = HTML::Pipeline::SanitizationFilter::WHITELIST + + # Allow `class` and `id` on all elements + whitelist[:attributes][:all].push('class', 'id') + + # Allow table alignment + whitelist[:attributes]['th'] = %w(style) + whitelist[:attributes]['td'] = %w(style) + + # Allow span elements + whitelist[:elements].push('span') + + # Remove `rel` attribute from `a` elements + whitelist[:transformers].push(remove_rel) + + whitelist + end + + def remove_rel + lambda do |env| + if env[:node_name] == 'a' + env[:node].remove_attribute('rel') + end + end + end + end + end +end diff --git a/lib/gitlab/markdown/table_of_contents_filter.rb b/lib/gitlab/markdown/table_of_contents_filter.rb new file mode 100644 index 0000000000000000000000000000000000000000..c97612dafb8eca4510be2688aa27e3e271cbd60c --- /dev/null +++ b/lib/gitlab/markdown/table_of_contents_filter.rb @@ -0,0 +1,62 @@ +require 'html/pipeline/filter' + +module Gitlab + module Markdown + # HTML filter that adds an anchor child element to all Headers in a + # document, so that they can be linked to. + # + # Generates the Table of Contents with links to each header. See Results. + # + # Based on HTML::Pipeline::TableOfContentsFilter. + # + # Context options: + # :no_header_anchors - Skips all processing done by this filter. + # + # Results: + # :toc - String containing Table of Contents data as a `ul` element with + # `li` child elements. + class TableOfContentsFilter < HTML::Pipeline::Filter + PUNCTUATION_REGEXP = /[^\p{Word}\- ]/u + + def call + return doc if context[:no_header_anchors] + + result[:toc] = "" + + headers = Hash.new(0) + + doc.css('h1, h2, h3, h4, h5, h6').each do |node| + text = node.text + + id = text.downcase + id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation + id.gsub!(' ', '-') # replace spaces with dash + id.squeeze!(' -') # replace multiple spaces or dashes with one + + uniq = (headers[id] > 0) ? "-#{headers[id]}" : '' + headers[id] += 1 + + if header_content = node.children.first + href = "#{id}#{uniq}" + push_toc(href, text) + header_content.add_previous_sibling(anchor_tag(href)) + end + end + + result[:toc] = %Q{<ul class="section-nav">\n#{result[:toc]}</ul>} unless result[:toc].empty? + + doc + end + + private + + def anchor_tag(href) + %Q{<a id="#{href}" class="anchor" href="##{href}" aria-hidden="true"></a>} + end + + def push_toc(href, text) + result[:toc] << %Q{<li><a href="##{href}">#{text}</a></li>\n} + end + end + end +end diff --git a/lib/gitlab/theme.rb b/lib/gitlab/theme.rb index f0e61aa2e81ad6b8c94652f7b8b55c814e04fc48..e5a1f1b44d96b28edae0007406cbafa2b09931a0 100644 --- a/lib/gitlab/theme.rb +++ b/lib/gitlab/theme.rb @@ -40,7 +40,7 @@ module Gitlab end # Convenience method to get a space-separated String of all the theme - # classes that mighty be applied to the `body` element + # classes that might be applied to the `body` element # # Returns a String def self.body_classes diff --git a/lib/redcarpet/render/gitlab_html.rb b/lib/redcarpet/render/gitlab_html.rb index 10efff2ae9f12f7b250c82f2cd7907a27bd7e32b..bea66e6cdc12ee10c1eeefdc702a708e7368a5aa 100644 --- a/lib/redcarpet/render/gitlab_html.rb +++ b/lib/redcarpet/render/gitlab_html.rb @@ -1,5 +1,6 @@ -class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML +require 'active_support/core_ext/string/output_safety' +class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML attr_reader :template alias_method :h, :template @@ -8,24 +9,12 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML @color_scheme = color_scheme @project = @template.instance_variable_get("@project") @options = options.dup - super options - end - def preprocess(full_document) - # Redcarpet doesn't allow SMB links when `safe_links_only` is enabled. - # FTP links are allowed, so we trick Redcarpet. - full_document.gsub("smb://", "ftp://smb:") + super(options) end - # If project has issue number 39, apostrophe will be linked in - # regular text to the issue as Redcarpet will convert apostrophe to - # #39; - # We replace apostrophe with right single quote before Redcarpet - # does the processing and put the apostrophe back in postprocessing. - # This only influences regular text, code blocks are untouched. def normal_text(text) - return text unless text.present? - text.gsub("'", "’") + ERB::Util.html_escape_once(text) end # Stolen from Rugments::Plugins::Redcarpet as this module is not required @@ -37,7 +26,7 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML # so we assume you're not using leading spaces that aren't tabs, # and just replace them here. if lexer.tag == 'make' - code.gsub! /^ /, "\t" + code.gsub!(/^ /, "\t") end formatter = Rugments::Formatters::HTML.new( @@ -46,27 +35,11 @@ class Redcarpet::Render::GitlabHTML < Redcarpet::Render::HTML formatter.format(lexer.lex(code)) end - def link(link, title, content) - h.link_to_gfm(content, link, title: title) - end - - def header(text, level) - if @options[:no_header_anchors] - "<h#{level}>#{text}</h#{level}>" - else - id = ActionController::Base.helpers.strip_tags(h.gfm(text)).downcase() \ - .gsub(/[^a-z0-9_-]/, '-').gsub(/-+/, '-').gsub(/^-/, '').gsub(/-$/, '') - "<h#{level} id=\"#{id}\">#{text}<a href=\"\##{id}\"></a></h#{level}>" - end - end - def postprocess(full_document) - full_document.gsub!("ftp://smb:", "smb://") - - full_document.gsub!("’", "'") unless @template.instance_variable_get("@project_wiki") || @project.nil? full_document = h.create_relative_links(full_document) end + h.gfm_with_options(full_document, @options) end end diff --git a/spec/controllers/import/google_code_controller_spec.rb b/spec/controllers/import/google_code_controller_spec.rb index 037cddb460020c34af6a489de6707f0a86f02fd6..78c0f5079cc6ee6157ff7a35486493e178dda94c 100644 --- a/spec/controllers/import/google_code_controller_spec.rb +++ b/spec/controllers/import/google_code_controller_spec.rb @@ -27,21 +27,34 @@ describe Import::GoogleCodeController do it "assigns variables" do @project = create(:project, import_type: 'google_code', creator_id: user.id) controller.stub_chain(:client, :repos).and_return([@repo]) + controller.stub_chain(:client, :incompatible_repos).and_return([]) get :status expect(assigns(:already_added_projects)).to eq([@project]) expect(assigns(:repos)).to eq([@repo]) + expect(assigns(:incompatible_repos)).to eq([]) end it "does not show already added project" do @project = create(:project, import_type: 'google_code', creator_id: user.id, import_source: 'vim') controller.stub_chain(:client, :repos).and_return([@repo]) + controller.stub_chain(:client, :incompatible_repos).and_return([]) get :status expect(assigns(:already_added_projects)).to eq([@project]) expect(assigns(:repos)).to eq([]) end + + it "does not show any invalid projects" do + controller.stub_chain(:client, :repos).and_return([]) + controller.stub_chain(:client, :incompatible_repos).and_return([@repo]) + + get :status + + expect(assigns(:repos)).to be_empty + expect(assigns(:incompatible_repos)).to eq([@repo]) + end end end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 57fa079d753894f7b9f542325222f4888f1b70ce..102678a1d74f1baa768ed9cd9971e04c68193872 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -94,10 +94,26 @@ FactoryGirl.define do 'new_issue_url' => 'http://redmine/projects/project_name_in_redmine/issues/new' } ) - end - after :create do |project| + project.issues_tracker = 'redmine' project.issues_tracker_id = 'project_name_in_redmine' end end + + factory :jira_project, parent: :project do + after :create do |project| + project.create_jira_service( + active: true, + properties: { + 'title' => 'JIRA tracker', + 'project_url' => 'http://jira.example/issues/?jql=project=A', + 'issues_url' => 'http://jira.example/browse/:id', + 'new_issue_url' => 'http://jira.example/secure/CreateIssue.jspa' + } + ) + + project.issues_tracker = 'jira' + project.issues_tracker_id = 'project_name_in_jira' + end + end end diff --git a/spec/features/markdown_spec.rb b/spec/features/markdown_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..3528200e12bdf445e7d1c01ee6eb473f954847d3 --- /dev/null +++ b/spec/features/markdown_spec.rb @@ -0,0 +1,391 @@ +require 'spec_helper' +require 'erb' + +# This feature spec is intended to be a comprehensive exercising of all of +# GitLab's non-standard Markdown parsing and the integration thereof. +# +# These tests should be very high-level. Anything low-level belongs in the specs +# for the corresponding HTML::Pipeline filter or helper method. +# +# The idea is to pass a Markdown document through our entire processing stack. +# +# The process looks like this: +# +# Raw Markdown +# -> `markdown` helper +# -> Redcarpet::Render::GitlabHTML converts Markdown to HTML +# -> Post-process HTML +# -> `gfm_with_options` helper +# -> HTML::Pipeline +# -> Sanitize +# -> Emoji +# -> Table of Contents +# -> Autolinks +# -> Rinku (http, https, ftp) +# -> Other schemes +# -> References +# -> `html_safe` +# -> Template +# +# See the MarkdownFeature class for setup details. + +describe 'GitLab Markdown' do + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + include Capybara::Node::Matchers + include GitlabMarkdownHelper + + # `markdown` calls these two methods + def current_user + @feat.user + end + + def user_color_scheme_class + :white + end + + # Let's only parse this thing once + before(:all) do + @feat = MarkdownFeature.new + + # `markdown` expects a `@project` variable + @project = @feat.project + + @md = markdown(@feat.raw_markdown) + @doc = Nokogiri::HTML::DocumentFragment.parse(@md) + end + + after(:all) do + @feat.teardown + end + + # Given a header ID, goes to that element's parent (the header), then to its + # second sibling (the body). + def get_section(id) + @doc.at_css("##{id}").parent.next.next + end + + # it 'writes to a file' do + # File.open(Rails.root.join('tmp/capybara/markdown_spec.html'), 'w') do |file| + # file.puts @md + # end + # end + + describe 'Markdown' do + describe 'No Intra Emphasis' do + it 'does not parse emphasis inside of words' do + body = get_section('no-intra-emphasis') + expect(body.to_html).not_to match('foo<em>bar</em>baz') + end + end + + describe 'Tables' do + it 'parses table Markdown' do + body = get_section('tables') + expect(body).to have_selector('th:contains("Header")') + expect(body).to have_selector('th:contains("Row")') + expect(body).to have_selector('th:contains("Example")') + end + + it 'allows Markdown in tables' do + expect(@doc.at_css('td:contains("Baz")').children.to_html). + to eq '<strong>Baz</strong>' + end + end + + describe 'Fenced Code Blocks' do + it 'parses fenced code blocks' do + expect(@doc).to have_selector('pre.code.highlight.white.c') + expect(@doc).to have_selector('pre.code.highlight.white.python') + end + end + + describe 'Strikethrough' do + it 'parses strikethroughs' do + expect(@doc).to have_selector(%{del:contains("and this text doesn't")}) + end + end + + describe 'Superscript' do + it 'parses superscript' do + body = get_section('superscript') + expect(body.to_html).to match('1<sup>st</sup>') + expect(body.to_html).to match('2<sup>nd</sup>') + end + end + end + + describe 'HTML::Pipeline' do + describe 'SanitizationFilter' do + it 'uses a permissive whitelist' do + expect(@doc).to have_selector('b#manual-b') + expect(@doc).to have_selector('em#manual-em') + expect(@doc).to have_selector("code#manual-code") + expect(@doc).to have_selector('kbd:contains("s")') + expect(@doc).to have_selector('strike:contains(Emoji)') + expect(@doc).to have_selector('img#manual-img') + expect(@doc).to have_selector('br#manual-br') + expect(@doc).to have_selector('hr#manual-hr') + end + + it 'permits span elements' do + expect(@doc).to have_selector('span#span-class-light.light') + end + + it 'permits table alignment' do + expect(@doc.at_css('th:contains("Header")')['style']).to eq 'text-align: center' + expect(@doc.at_css('th:contains("Row")')['style']).to eq 'text-align: right' + expect(@doc.at_css('th:contains("Example")')['style']).to eq 'text-align: left' + + expect(@doc.at_css('td:contains("Foo")')['style']).to eq 'text-align: center' + expect(@doc.at_css('td:contains("Bar")')['style']).to eq 'text-align: right' + expect(@doc.at_css('td:contains("Baz")')['style']).to eq 'text-align: left' + end + + it 'removes `rel` attribute from links' do + expect(@doc).to have_selector('a#a-rel-nofollow') + expect(@doc).not_to have_selector('a#a-rel-nofollow[rel]') + end + + it "removes `href` from `a` elements if it's fishy" do + expect(@doc).to have_selector('a#a-href-javascript') + expect(@doc).not_to have_selector('a#a-href-javascript[href]') + end + end + + describe 'Escaping' do + let(:table) { @doc.css('table').last.at_css('tbody') } + + it 'escapes non-tag angle brackets' do + expect(table.at_xpath('.//tr[1]/td[3]').inner_html).to eq '1 < 3 & 5' + end + end + + describe 'EmojiFilter' do + it 'parses Emoji' do + expect(@doc).to have_selector('img.emoji', count: 10) + end + end + + describe 'TableOfContentsFilter' do + it 'creates anchors inside header elements' do + expect(@doc).to have_selector('h1 a#gitlab-markdown') + expect(@doc).to have_selector('h2 a#markdown') + expect(@doc).to have_selector('h3 a#autolinkfilter') + end + end + + describe 'AutolinkFilter' do + let(:list) { get_section('autolinkfilter').parent.search('ul') } + + def item(index) + list.at_css("li:nth-child(#{index})") + end + + it 'autolinks http://' do + expect(item(1).children.first.name).to eq 'a' + expect(item(1).children.first['href']).to eq 'http://about.gitlab.com/' + end + + it 'autolinks https://' do + expect(item(2).children.first.name).to eq 'a' + expect(item(2).children.first['href']).to eq 'https://google.com/' + end + + it 'autolinks ftp://' do + expect(item(3).children.first.name).to eq 'a' + expect(item(3).children.first['href']).to eq 'ftp://ftp.us.debian.org/debian/' + end + + it 'autolinks smb://' do + expect(item(4).children.first.name).to eq 'a' + expect(item(4).children.first['href']).to eq 'smb://foo/bar/baz' + end + + it 'autolinks irc://' do + expect(item(5).children.first.name).to eq 'a' + expect(item(5).children.first['href']).to eq 'irc://irc.freenode.net/git' + end + + it 'autolinks short, invalid URLs' do + expect(item(6).children.first.name).to eq 'a' + expect(item(6).children.first['href']).to eq 'http://localhost:3000' + end + + %w(code a kbd).each do |elem| + it "ignores links inside '#{elem}' element" do + expect(@doc.at_css("#{elem}#autolink-#{elem}").child).to be_text + end + end + end + + describe 'ReferenceFilter' do + it 'handles references in headers' do + header = @doc.at_css('#reference-filters-eg-1').parent + + expect(header.css('a').size).to eq 2 + end + + it "handles references in Markdown" do + body = get_section('reference-filters-eg-1') + expect(body).to have_selector('em a.gfm-merge_request', count: 1) + end + + it 'parses user references' do + body = get_section('userreferencefilter') + expect(body).to have_selector('a.gfm.gfm-project_member', count: 3) + end + + it 'parses issue references' do + body = get_section('issuereferencefilter') + expect(body).to have_selector('a.gfm.gfm-issue', count: 2) + end + + it 'parses merge request references' do + body = get_section('mergerequestreferencefilter') + expect(body).to have_selector('a.gfm.gfm-merge_request', count: 2) + end + + it 'parses snippet references' do + body = get_section('snippetreferencefilter') + expect(body).to have_selector('a.gfm.gfm-snippet', count: 2) + end + + it 'parses commit range references' do + body = get_section('commitrangereferencefilter') + expect(body).to have_selector('a.gfm.gfm-commit_range', count: 2) + end + + it 'parses commit references' do + body = get_section('commitreferencefilter') + expect(body).to have_selector('a.gfm.gfm-commit', count: 2) + end + + it 'parses label references' do + body = get_section('labelreferencefilter') + expect(body).to have_selector('a.gfm.gfm-label', count: 3) + end + end + end +end + +# This is a helper class used by the GitLab Markdown feature spec +# +# Because the feature spec only cares about the output of the Markdown, and the +# test setup and teardown and parsing is fairly expensive, we only want to do it +# once. Unfortunately RSpec will not let you access `let`s in a `before(:all)` +# block, so we fake it by encapsulating all the shared setup in this class. +# +# The class contains the raw Markup used in the test, dynamically substituting +# real objects, created from factories and setup on-demand, when referenced in +# the Markdown. +class MarkdownFeature + include FactoryGirl::Syntax::Methods + + def initialize + DatabaseCleaner.start + end + + def teardown + DatabaseCleaner.clean + end + + def user + @user ||= create(:user) + end + + def group + unless @group + @group = create(:group) + @group.add_user(user, Gitlab::Access::DEVELOPER) + end + + @group + end + + # Direct references ---------------------------------------------------------- + + def project + @project ||= create(:project) + end + + def issue + @issue ||= create(:issue, project: project) + end + + def merge_request + @merge_request ||= create(:merge_request, :simple, source_project: project) + end + + def snippet + @snippet ||= create(:project_snippet, project: project) + end + + def commit + @commit ||= project.repository.commit + end + + def commit_range + unless @commit_range + commit2 = project.repository.commit('HEAD~3') + @commit_range = CommitRange.new("#{commit.id}...#{commit2.id}") + end + + @commit_range + end + + def simple_label + @simple_label ||= create(:label, name: 'gfm', project: project) + end + + def label + @label ||= create(:label, name: 'awaiting feedback', project: project) + end + + # Cross-references ----------------------------------------------------------- + + def xproject + unless @xproject + namespace = create(:namespace, name: 'cross-reference') + @xproject = create(:project, namespace: namespace) + @xproject.team << [user, :developer] + end + + @xproject + end + + # Shortcut to "cross-reference/project" + def xref + xproject.path_with_namespace + end + + def xissue + @xissue ||= create(:issue, project: xproject) + end + + def xmerge_request + @xmerge_request ||= create(:merge_request, :simple, source_project: xproject) + end + + def xsnippet + @xsnippet ||= create(:project_snippet, project: xproject) + end + + def xcommit + @xcommit ||= xproject.repository.commit + end + + def xcommit_range + unless @xcommit_range + xcommit2 = xproject.repository.commit('HEAD~2') + @xcommit_range = CommitRange.new("#{xcommit.id}...#{xcommit2.id}") + end + + @xcommit_range + end + + def raw_markdown + fixture = Rails.root.join('spec/fixtures/markdown.md.erb') + ERB.new(File.read(fixture)).result(binding) + end +end diff --git a/spec/fixtures/markdown.md.erb b/spec/fixtures/markdown.md.erb new file mode 100644 index 0000000000000000000000000000000000000000..0c1407585572d3e57ce10af744c665c344daae7d --- /dev/null +++ b/spec/fixtures/markdown.md.erb @@ -0,0 +1,178 @@ +# GitLab Markdown + +This document is intended to be a comprehensive example of custom GitLab +Markdown usage. It will be parsed and then tested for accuracy. Let's get +started. + +## Markdown + +GitLab uses [Redcarpet](http://git.io/ld_NVQ) to parse all Markdown into +HTML. + +It has some special features. Let's try 'em out! + +### No Intra Emphasis + +This string should have no emphasis: foo_bar_baz + +### Tables + +| Header | Row | Example | +| :------: | ---: | :------ | +| Foo | Bar | **Baz** | + +### Fenced Code Blocks + +```c +#include<stdio.h> + +main() +{ + printf("Hello World"); + +} +``` + +```python +print "Hello, World!" +``` + +### Strikethrough + +This text says this, ~~and this text doesn't~~. + +### Superscript + +This is my 1^(st) time using superscript in Markdown. Now this is my +2^(nd). + +### Next step + +After the Markdown has been turned into HTML, it gets passed through... + +## HTML::Pipeline + +### SanitizationFilter + +GitLab uses <a href="http://git.io/vfW8a" class="sanitize" id="sanitize-link">HTML::Pipeline::SanitizationFilter</a> +to sanitize the generated HTML, stripping dangerous or unwanted tags. + +Its default whitelist is pretty permissive. Check it: + +<b id="manual-b">This text is bold</b> and <em id="manual-em">this text is emphasized</em>. + +<code id="manual-code">echo "Hello, world!"</code> + +Press <kbd>s</kbd> to search. + +<strike>Emoji</strike> Plain old images! <img +src="http://www.emoji-cheat-sheet.com/graphics/emojis/smile.png" width="20" +height="20" id="manual-img" /> + +Here comes a line break: + +<br id="manual-br" /> + +And a horizontal rule: + +<hr id="manual-hr" /> + +As permissive as it is, we've allowed even more stuff: + +<span class="light" id="span-class-light">Span elements</span> + +<a href="#" rel="nofollow" id="a-rel-nofollow">This is a link with a defined rel attribute, which should be removed</a> + +<a href="javascript:alert('Hi')" id="a-href-javascript">This is a link trying to be sneaky. It gets its link removed entirely.</a> + +### Escaping + +The problem with SanitizationFilter is that it can be too aggressive. + +| Input | Expected | Actual | +| ----------- | ---------------- | --------- | +| `1 < 3 & 5` | 1 < 3 & 5 | 1 < 3 & 5 | +| `<foo>` | <foo> | <foo> | + +### EmojiFilter + +Because life would be :zzz: without Emoji, right? :rocket: + +Get ready for the Emoji :bomb:: :+1::-1::ok_hand::wave::v::raised_hand::muscle: + +### TableOfContentsFilter + +All headers in this document should be linkable. Try it. + +### AutolinkFilter + +These are all plain text that should get turned into links: + +- http://about.gitlab.com/ +- https://google.com/ +- ftp://ftp.us.debian.org/debian/ +- smb://foo/bar/baz +- irc://irc.freenode.net/git +- http://localhost:3000 + +But it shouldn't autolink text inside certain tags: + +- <code id="autolink-code">http://about.gitlab.com/</code> +- <a id="autolink-a">http://about.gitlab.com/</a> +- <kbd id="autolink-kbd">http://about.gitlab.com/</kbd> + +### Reference Filters (e.g., #<%= issue.iid %>) + +References should be parseable even inside _!<%= merge_request.iid %>_ emphasis. + +#### UserReferenceFilter + +- All: @all +- User: @<%= user.username %> +- Group: @<%= group.name %> +- Ignores invalid: @fake_user +- Ignored in code: `@<%= user.username %>` +- Ignored in links: [Link to @<%= user.username %>](#user-link) + +#### IssueReferenceFilter + +- Issue: #<%= issue.iid %> +- Issue in another project: <%= xref %>#<%= xissue.iid %> +- Ignored in code: `#<%= issue.iid %>` +- Ignored in links: [Link to #<%= issue.iid %>](#issue-link) + +#### MergeRequestReferenceFilter + +- Merge request: !<%= merge_request.iid %> +- Merge request in another project: <%= xref %>!<%= xmerge_request.iid %> +- Ignored in code: `!<%= merge_request.iid %>` +- Ignored in links: [Link to !<%= merge_request.iid %>](#merge-request-link) + +#### SnippetReferenceFilter + +- Snippet: $<%= snippet.id %> +- Snippet in another project: <%= xref %>$<%= xsnippet.id %> +- Ignored in code: `$<%= snippet.id %>` +- Ignored in links: [Link to $<%= snippet.id %>](#snippet-link) + +#### CommitRangeReferenceFilter + +- Range: <%= commit_range %> +- Range in another project: <%= xref %>@<%= xcommit_range %> +- Ignored in code: `<%= commit_range %>` +- Ignored in links: [Link to <%= commit_range %>](#commit-range-link) + +#### CommitReferenceFilter + +- Commit: <%= commit.id %> +- Commit in another project: <%= xref %>@<%= xcommit.id %> +- Ignored in code: `<%= commit.id %>` +- Ignored in links: [Link to <%= commit.id %>](#commit-link) + +#### LabelReferenceFilter + +- Label by ID: ~<%= simple_label.id %> +- Label by name: ~<%= simple_label.name %> +- Label by name in quotes: ~"<%= label.name %>" +- Ignored in code: `~<%= simple_label.name %>` +- Ignored in links: [Link to ~<%= simple_label.id %>](#label-link) diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index e309dbb6a2f9a6429b8b35aaec9de3ac6802f7b2..b6be82e41096483ce568a0f54eb5f35e4cff8beb 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -107,8 +107,7 @@ describe GitlabMarkdownHelper do end it 'should not be confused by whitespace before bullets' do - rendered_text_asterisk = markdown(@source_text_asterisk, - parse_tasks: true) + rendered_text_asterisk = markdown(@source_text_asterisk, parse_tasks: true) rendered_text_dash = markdown(@source_text_dash, parse_tasks: true) expect(rendered_text_asterisk).to match( @@ -207,78 +206,7 @@ describe GitlabMarkdownHelper do end describe "#markdown" do - # TODO (rspeicher) - This block tests multiple different contexts. Break this up! - - it "should add ids and links to headers" do - # Test every rule except nested tags. - text = '..Ab_c-d. e..' - id = 'ab_c-d-e' - expect(markdown("# #{text}")). - to match(%r{<h1 id="#{id}">#{text}<a href="[^"]*##{id}"></a></h1>}) - expect(markdown("# #{text}", {no_header_anchors:true})). - to eq("<h1>#{text}</h1>") - - id = 'link-text' - expect(markdown("# [link text](url) ")).to match( - %r{<h1 id="#{id}"><a href="[^"]*url">link text</a> <img[^>]*><a href="[^"]*##{id}"></a></h1>} - ) - end - - # REFERENCES (PART TWO: THE REVENGE) --------------------------------------- - - it "should handle references in headers" do - actual = "\n# Working around ##{issue.iid}\n## Apply !#{merge_request.iid}" - - expect(markdown(actual, no_header_anchors: true)). - to match(%r{<h1[^<]*>Working around <a.+>##{issue.iid}</a></h1>}) - expect(markdown(actual, no_header_anchors: true)). - to match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.iid}</a></h2>}) - end - - it "should handle references in <em>" do - actual = "Apply _!#{merge_request.iid}_ ASAP" - - expect(markdown(actual)). - to match(%r{Apply <em><a.+>!#{merge_request.iid}</a></em>}) - end - - # CODE BLOCKS ------------------------------------------------------------- - - it "should leave code blocks untouched" do - allow(helper).to receive(:current_user).and_return(user) - allow(helper).to receive(:user_color_scheme_class).and_return(:white) - - target_html = "<pre class=\"code highlight white plaintext\"><code>some code from $#{snippet.id}\nhere too\n</code></pre>\n" - - expect(markdown("\n some code from $#{snippet.id}\n here too\n")). - to eq(target_html) - expect(markdown("\n```\nsome code from $#{snippet.id}\nhere too\n```\n")). - to eq(target_html) - end - - it "should leave inline code untouched" do - expect(markdown("Don't use `$#{snippet.id}` here.")). - to eq "<p>Don't use <code>$#{snippet.id}</code> here.</p>\n" - end - - # REF-LIKE AUTOLINKS? ----------------------------------------------------- - # Basically: Don't parse references inside `<a>` tags. - - it "should leave ref-like autolinks untouched" do - expect(markdown("look at http://example.tld/#!#{merge_request.iid}")).to eq("<p>look at <a href=\"http://example.tld/#!#{merge_request.iid}\">http://example.tld/#!#{merge_request.iid}</a></p>\n") - end - - it "should leave ref-like href of 'manual' links untouched" do - expect(markdown("why not [inspect !#{merge_request.iid}](http://example.tld/#!#{merge_request.iid})")).to eq("<p>why not <a href=\"http://example.tld/#!#{merge_request.iid}\">inspect </a><a href=\"#{namespace_project_merge_request_path(project.namespace, project, merge_request)}\" title=\"Merge Request: #{merge_request.title}\" class=\"gfm gfm-merge_request\">!#{merge_request.iid}</a><a href=\"http://example.tld/#!#{merge_request.iid}\"></a></p>\n") - end - - it "should leave ref-like src of images untouched" do - expect(markdown("screen shot: ")).to eq("<p>screen shot: <img src=\"http://example.tld/#!#{merge_request.iid}\" alt=\"some image\"></p>\n") - end - - # RELATIVE URLS ----------------------------------------------------------- # TODO (rspeicher): These belong in a relative link filter spec - context 'relative links' do context 'with a valid repository' do before do @@ -333,11 +261,6 @@ describe GitlabMarkdownHelper do expected = "" expect(markdown(actual)).to match(expected) end - - it 'should allow whitelisted HTML tags from the user' do - actual = '<dl><dt>Term</dt><dd>Definition</dd></dl>' - expect(markdown(actual)).to match(actual) - end end context 'with an empty repository' do @@ -353,34 +276,6 @@ describe GitlabMarkdownHelper do end end end - - # SANITIZATION ------------------------------------------------------------ - # TODO (rspeicher): These are testing SanitizationFilter, not `markdown` - - it 'should sanitize tags that are not whitelisted' do - actual = '<textarea>no inputs allowed</textarea> <blink>no blinks</blink>' - expected = 'no inputs allowed no blinks' - expect(markdown(actual)).to match(expected) - expect(markdown(actual)).not_to match('<.textarea>') - expect(markdown(actual)).not_to match('<.blink>') - end - - it 'should allow whitelisted tag attributes from the user' do - actual = '<a class="custom">link text</a>' - expect(markdown(actual)).to match(actual) - end - - it 'should sanitize tag attributes that are not whitelisted' do - actual = '<a href="http://example.com/bar.html" foo="bar">link text</a>' - expected = '<a href="http://example.com/bar.html">link text</a>' - expect(markdown(actual)).to match(expected) - end - - it 'should sanitize javascript in attributes' do - actual = %q(<a href="javascript:alert('foo')">link text</a>) - expected = '<a>link text</a>' - expect(markdown(actual)).to match(expected) - end end describe '#render_wiki_content' do diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 54dd8d4aa64dd87686e982499c9e3940f2c8f740..c08ddb4cae1bd6ba25dd6a110b8cb9cead4a67c6 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -5,24 +5,6 @@ describe IssuesHelper do let(:issue) { create :issue, project: project } let(:ext_project) { create :redmine_project } - describe "title_for_issue" do - it "should return issue title if used internal tracker" do - @project = project - expect(title_for_issue(issue.iid)).to eq issue.title - end - - it "should always return empty string if used external tracker" do - @project = ext_project - expect(title_for_issue(rand(100))).to eq "" - end - - it "should always return empty string if project nil" do - @project = nil - - expect(title_for_issue(rand(100))).to eq "" - end - end - describe "url_for_project_issues" do let(:project_url) { ext_project.external_issue_tracker.project_url } let(:ext_expected) do diff --git a/spec/lib/gitlab/google_code_import/client_spec.rb b/spec/lib/gitlab/google_code_import/client_spec.rb index d2bf871daa8bd1133375669d7a6e53c61258490d..a66b811e0fd1df3b48ee4f5ee82873fdc35caca5 100644 --- a/spec/lib/gitlab/google_code_import/client_spec.rb +++ b/spec/lib/gitlab/google_code_import/client_spec.rb @@ -23,6 +23,7 @@ describe Gitlab::GoogleCodeImport::Client do describe "#repos" do it "returns only Git repositories" do expect(subject.repos.length).to eq(1) + expect(subject.incompatible_repos.length).to eq(1) end end diff --git a/spec/lib/gitlab/markdown/autolink_filter_spec.rb b/spec/lib/gitlab/markdown/autolink_filter_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..0bbdc11a9798f6b82c3a7f8632ac63e4f6fe09f8 --- /dev/null +++ b/spec/lib/gitlab/markdown/autolink_filter_spec.rb @@ -0,0 +1,106 @@ +require 'spec_helper' + +module Gitlab::Markdown + describe AutolinkFilter do + let(:link) { 'http://about.gitlab.com/' } + + def filter(html, options = {}) + described_class.call(html, options) + end + + it 'does nothing when :autolink is false' do + exp = act = link + expect(filter(act, autolink: false).to_html).to eq exp + end + + it 'does nothing with non-link text' do + exp = act = 'This text contains no links to autolink' + expect(filter(act).to_html).to eq exp + end + + context 'Rinku schemes' do + it 'autolinks http' do + doc = filter("See #{link}") + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'autolinks https' do + link = 'https://google.com/' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'autolinks ftp' do + link = 'ftp://ftp.us.debian.org/debian/' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'autolinks short URLs' do + link = 'http://localhost:3000/' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'accepts link_attr options' do + doc = filter("See #{link}", link_attr: {class: 'custom'}) + + expect(doc.at_css('a')['class']).to eq 'custom' + end + + described_class::IGNORE_PARENTS.each do |elem| + it "ignores valid links contained inside '#{elem}' element" do + exp = act = "<#{elem}>See #{link}</#{elem}>" + expect(filter(act).to_html).to eq exp + end + end + end + + context 'other schemes' do + let(:link) { 'foo://bar.baz/' } + + it 'autolinks smb' do + link = 'smb:///Volumes/shared/foo.pdf' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'autolinks irc' do + link = 'irc://irc.freenode.net/git' + doc = filter("See #{link}") + + expect(doc.at_css('a').text).to eq link + expect(doc.at_css('a')['href']).to eq link + end + + it 'does not include trailing punctuation' do + doc = filter("See #{link}.") + expect(doc.at_css('a').text).to eq link + + doc = filter("See #{link}, ok?") + expect(doc.at_css('a').text).to eq link + end + + it 'accepts link_attr options' do + doc = filter("See #{link}", link_attr: {class: 'custom'}) + expect(doc.at_css('a')['class']).to eq 'custom' + end + + described_class::IGNORE_PARENTS.each do |elem| + it "ignores valid links contained inside '#{elem}' element" do + exp = act = "<#{elem}>See #{link}</#{elem}>" + expect(filter(act).to_html).to eq exp + end + end + end + end +end diff --git a/spec/lib/gitlab/markdown/external_issue_reference_filter_spec.rb b/spec/lib/gitlab/markdown/external_issue_reference_filter_spec.rb index 27e930ef7daf3df4aae5a249808fa21158aada4f..b19bc125b92cc7eb406df611b9849f704fae3a11 100644 --- a/spec/lib/gitlab/markdown/external_issue_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/external_issue_reference_filter_spec.rb @@ -8,29 +8,12 @@ module Gitlab::Markdown IssuesHelper end - let(:project) { create(:empty_project) } + let(:project) { create(:jira_project) } let(:issue) { double('issue', iid: 123) } context 'JIRA issue references' do let(:reference) { "JIRA-#{issue.iid}" } - before do - jira = project.create_jira_service - - props = { - 'title' => 'JIRA tracker', - 'project_url' => 'http://jira.example/issues/?jql=project=A', - 'issues_url' => 'http://jira.example/browse/:id', - 'new_issue_url' => 'http://jira.example/secure/CreateIssue.jspa' - } - - jira.update_attributes(properties: props, active: true) - end - - after do - project.jira_service.destroy - end - it 'requires project context' do expect { described_class.call('Issue JIRA-123', {}) }. to raise_error(ArgumentError, /:project/) diff --git a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb index 393bf32e19610c632fd310b53af2e8f4e7920902..08382b3e7e87a2c718358423dfe159861f215ffb 100644 --- a/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb +++ b/spec/lib/gitlab/markdown/issue_reference_filter_spec.rb @@ -27,7 +27,7 @@ module Gitlab::Markdown let(:reference) { "##{issue.iid}" } it 'ignores valid references when using non-default tracker' do - expect(project).to receive(:issue_exists?).with(issue.iid).and_return(false) + expect(project).to receive(:get_issue).with(issue.iid).and_return(nil) exp = act = "Issue ##{issue.iid}" expect(filter(act).to_html).to eq exp @@ -48,7 +48,7 @@ module Gitlab::Markdown it 'ignores invalid issue IDs' do exp = act = "Fixed ##{issue.iid + 1}" - expect(project).to receive(:issue_exists?).with(issue.iid + 1) + expect(project).to receive(:get_issue).with(issue.iid + 1).and_return(nil) expect(filter(act).to_html).to eq exp end @@ -98,8 +98,8 @@ module Gitlab::Markdown before { allow_cross_reference! } it 'ignores valid references when cross-reference project uses external tracker' do - expect_any_instance_of(Project).to receive(:issue_exists?). - with(issue.iid).and_return(false) + expect_any_instance_of(Project).to receive(:get_issue). + with(issue.iid).and_return(nil) exp = act = "Issue ##{issue.iid}" expect(filter(act).to_html).to eq exp diff --git a/spec/lib/gitlab/markdown/sanitization_filter_spec.rb b/spec/lib/gitlab/markdown/sanitization_filter_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..ab909a686351ac469097b6176d0d0158cd81b126 --- /dev/null +++ b/spec/lib/gitlab/markdown/sanitization_filter_spec.rb @@ -0,0 +1,81 @@ +require 'spec_helper' + +module Gitlab::Markdown + describe SanitizationFilter do + def filter(html, options = {}) + described_class.call(html, options) + end + + describe 'default whitelist' do + it 'sanitizes tags that are not whitelisted' do + act = %q{<textarea>no inputs</textarea> and <blink>no blinks</blink>} + exp = 'no inputs and no blinks' + expect(filter(act).to_html).to eq exp + end + + it 'sanitizes tag attributes' do + act = %q{<a href="http://example.com/bar.html" onclick="bar">Text</a>} + exp = %q{<a href="http://example.com/bar.html">Text</a>} + expect(filter(act).to_html).to eq exp + end + + it 'sanitizes javascript in attributes' do + act = %q(<a href="javascript:alert('foo')">Text</a>) + exp = '<a>Text</a>' + expect(filter(act).to_html).to eq exp + end + + it 'allows whitelisted HTML tags from the user' do + exp = act = "<dl>\n<dt>Term</dt>\n<dd>Definition</dd>\n</dl>" + expect(filter(act).to_html).to eq exp + end + end + + describe 'custom whitelist' do + it 'allows `class` attribute on any element' do + exp = act = %q{<strong class="foo">Strong</strong>} + expect(filter(act).to_html).to eq exp + end + + it 'allows `id` attribute on any element' do + exp = act = %q{<em id="foo">Emphasis</em>} + expect(filter(act).to_html).to eq exp + end + + it 'allows `style` attribute on table elements' do + html = <<-HTML.strip_heredoc + <table> + <tr><th style="text-align: center">Head</th></tr> + <tr><td style="text-align: right">Body</th></tr> + </table> + HTML + + doc = filter(html) + + expect(doc.at_css('th')['style']).to eq 'text-align: center' + expect(doc.at_css('td')['style']).to eq 'text-align: right' + end + + it 'allows `span` elements' do + exp = act = %q{<span>Hello</span>} + expect(filter(act).to_html).to eq exp + end + + it 'removes `rel` attribute from `a` elements' do + doc = filter(%q{<a href="#" rel="nofollow">Link</a>}) + + expect(doc.css('a').size).to eq 1 + expect(doc.at_css('a')['href']).to eq '#' + expect(doc.at_css('a')['rel']).to be_nil + end + + it 'removes script-like `href` attribute from `a` elements' do + html = %q{<a href="javascript:alert('Hi')">Hi</a>} + doc = filter(html) + + expect(doc.css('a').size).to eq 1 + expect(doc.at_css('a')['href']).to be_nil + end + end + end +end diff --git a/spec/lib/gitlab/markdown/table_of_contents_filter_spec.rb b/spec/lib/gitlab/markdown/table_of_contents_filter_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..f383a5850d5419ca307b45f317225d31f993d938 --- /dev/null +++ b/spec/lib/gitlab/markdown/table_of_contents_filter_spec.rb @@ -0,0 +1,101 @@ +# encoding: UTF-8 + +require 'spec_helper' + +module Gitlab::Markdown + describe TableOfContentsFilter do + def filter(html, options = {}) + described_class.call(html, options) + end + + def header(level, text) + "<h#{level}>#{text}</h#{level}>\n" + end + + it 'does nothing when :no_header_anchors is truthy' do + exp = act = header(1, 'Header') + expect(filter(act, no_header_anchors: 1).to_html).to eq exp + end + + it 'does nothing with empty headers' do + exp = act = header(1, nil) + expect(filter(act).to_html).to eq exp + end + + 1.upto(6) do |i| + it "processes h#{i} elements" do + html = header(i, "Header #{i}") + doc = filter(html) + + expect(doc.css("h#{i} a").first.attr('id')).to eq "header-#{i}" + end + end + + describe 'anchor tag' do + it 'has an `anchor` class' do + doc = filter(header(1, 'Header')) + expect(doc.css('h1 a').first.attr('class')).to eq 'anchor' + end + + it 'links to the id' do + doc = filter(header(1, 'Header')) + expect(doc.css('h1 a').first.attr('href')).to eq '#header' + end + + describe 'generated IDs' do + it 'translates spaces to dashes' do + doc = filter(header(1, 'This header has spaces in it')) + expect(doc.css('h1 a').first.attr('id')).to eq 'this-header-has-spaces-in-it' + end + + it 'squeezes multiple spaces and dashes' do + doc = filter(header(1, 'This---header is poorly-formatted')) + expect(doc.css('h1 a').first.attr('id')).to eq 'this-header-is-poorly-formatted' + end + + it 'removes punctuation' do + doc = filter(header(1, "This, header! is, filled. with @ punctuation?")) + expect(doc.css('h1 a').first.attr('id')).to eq 'this-header-is-filled-with-punctuation' + end + + it 'appends a unique number to duplicates' do + doc = filter(header(1, 'One') + header(2, 'One')) + + expect(doc.css('h1 a').first.attr('id')).to eq 'one' + expect(doc.css('h2 a').first.attr('id')).to eq 'one-1' + end + + it 'supports Unicode' do + doc = filter(header(1, '한글')) + expect(doc.css('h1 a').first.attr('id')).to eq '한글' + expect(doc.css('h1 a').first.attr('href')).to eq '#한글' + end + end + end + + describe 'result' do + def result(html) + HTML::Pipeline.new([described_class]).call(html) + end + + let(:results) { result(header(1, 'Header 1') + header(2, 'Header 2')) } + let(:doc) { Nokogiri::XML::DocumentFragment.parse(results[:toc]) } + + it 'is contained within a `ul` element' do + expect(doc.children.first.name).to eq 'ul' + expect(doc.children.first.attr('class')).to eq 'section-nav' + end + + it 'contains an `li` element for each header' do + expect(doc.css('li').length).to eq 2 + + links = doc.css('li a') + + expect(links.first.attr('href')).to eq '#header-1' + expect(links.first.text).to eq 'Header 1' + expect(links.last.attr('href')).to eq '#header-2' + expect(links.last.text).to eq 'Header 2' + end + end + end +end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index d28b4768545e2d5196a4f08dc475cdd03ce720a1..dbcf7286e45907e87f4e56353d96fbfcebbbbcf1 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -11,9 +11,8 @@ describe Notify do let(:recipient) { create(:user, email: 'recipient@example.com') } let(:project) { create(:project) } - around(:each) { ActionMailer::Base.deliveries.clear } - before(:each) do + ActionMailer::Base.deliveries.clear email = recipient.emails.create(email: "notifications@example.com") recipient.update_attribute(:notification_email, email.email) end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 879a63dd9f954585e08e46ce4618ce62e6dd84c5..37e21a9081835ad0b1cb7db750e83aad048c3f79 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -129,6 +129,48 @@ describe Project do end end + describe '#get_issue' do + let(:project) { create(:empty_project) } + let(:issue) { create(:issue, project: project) } + + context 'with default issues tracker' do + it 'returns an issue' do + expect(project.get_issue(issue.iid)).to eq issue + end + + it 'returns nil when no issue found' do + expect(project.get_issue(999)).to be_nil + end + end + + context 'with external issues tracker' do + before do + allow(project).to receive(:default_issues_tracker?).and_return(false) + end + + it 'returns an ExternalIssue' do + issue = project.get_issue('FOO-1234') + expect(issue).to be_kind_of(ExternalIssue) + expect(issue.iid).to eq 'FOO-1234' + expect(issue.project).to eq project + end + end + end + + describe '#issue_exists?' do + let(:project) { create(:empty_project) } + + it 'is truthy when issue exists' do + expect(project).to receive(:get_issue).and_return(double) + expect(project.issue_exists?(1)).to be_truthy + end + + it 'is falsey when issue does not exist' do + expect(project).to receive(:get_issue).and_return(nil) + expect(project.issue_exists?(1)).to be_falsey + end + end + describe :update_merge_requests do let(:project) { create(:project) } let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } @@ -180,25 +222,6 @@ describe Project do end end - describe :issue_exists? do - let(:project) { create(:project) } - let(:existed_issue) { create(:issue, project: project) } - let(:not_existed_issue) { create(:issue) } - let(:ext_project) { create(:redmine_project) } - - it 'should be true or if used internal tracker and issue exists' do - expect(project.issue_exists?(existed_issue.iid)).to be_truthy - end - - it 'should be false or if used internal tracker and issue not exists' do - expect(project.issue_exists?(not_existed_issue.iid)).to be_falsey - end - - it 'should always be true if used other tracker' do - expect(ext_project.issue_exists?(rand(100))).to be_truthy - end - end - describe :default_issues_tracker? do let(:project) { create(:project) } let(:ext_project) { create(:redmine_project) } diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index d1844bd2b878e1003c538f49e5bd2873131f7745..6d4a806791012e9b6ab7a404d98c583e82095980 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -35,6 +35,7 @@ module TestEnv # Create repository for FactoryGirl.create(:project) setup_factory_repo + # Create repository for FactoryGirl.create(:forked_project_with_submodules) setup_forked_repo end @@ -54,7 +55,7 @@ module TestEnv tmp_test_path = Rails.root.join('tmp', 'tests', '**') Dir[tmp_test_path].each do |entry| - unless File.basename(entry) =~ /\Agitlab-(shell|test)\z/ + unless File.basename(entry) =~ /\Agitlab-(shell|test|test-fork)\z/ FileUtils.rm_rf(entry) end end