From 20037e61122a688366060f9427506962048e77ed Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 7 Jul 2016 21:03:21 +0800 Subject: Introduce Project#builds_for(build_name, ref = 'HEAD'): So that we could find the particular builds according to build_name and ref. It would be used to find the latest build artifacts from a particular branch or tag. --- app/models/commit_status.rb | 8 +++++++- app/models/project.rb | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index e437e3417a8..6828705dbc8 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -16,7 +16,13 @@ class CommitStatus < ActiveRecord::Base alias_attribute :author, :user - scope :latest, -> { where(id: unscope(:select).select('max(id)').group(:name, :commit_id)) } + scope :latest, -> do + id = unscope(:select). + select("max(#{table_name}.id)"). + group(:name, :commit_id) + + where(id: id) + end scope :retried, -> { where.not(id: latest) } scope :ordered, -> { order(:name) } scope :ignored, -> { where(allow_failure: true, status: [:failed, :canceled]) } diff --git a/app/models/project.rb b/app/models/project.rb index 029026a4e56..293dbd52359 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -429,6 +429,14 @@ class Project < ActiveRecord::Base repository.commit(id) end + def builds_for(build_name, ref = 'HEAD') + sha = commit(ref).sha + + builds.joins(:pipeline). + merge(Ci::Pipeline.where(sha: sha)). + where(name: build_name) + end + def merge_base_commit(first_commit_id, second_commit_id) sha = repository.merge_base(first_commit_id, second_commit_id) repository.commit(sha) if sha -- cgit v1.2.1 From f601ec54fcfad7f365d3488c0a48575862c48958 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 11 Jul 2016 18:17:32 +0800 Subject: Introduce Projects::ArtifactsController#search: So we redirect from ref and build_name to the particular build, namely: * /u/r/artifacts/ref/build_name/* -> /u/r/builds/:build_id/artifacts/* For: * download * browse * file --- app/controllers/projects/artifacts_controller.rb | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index f11c8321464..c00295cd3b5 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -35,14 +35,34 @@ class Projects::ArtifactsController < Projects::ApplicationController redirect_to namespace_project_build_path(project.namespace, project, build) end + def search + url = namespace_project_build_url(project.namespace, project, build) + + if params[:path] + redirect_to "#{url}/artifacts/#{params[:path]}" + else + render_404 + end + end + private def validate_artifacts! - render_404 unless build.artifacts? + render_404 unless build && build.artifacts? end def build - @build ||= project.builds.find_by!(id: params[:build_id]) + @build ||= build_from_id || build_from_ref + end + + def build_from_id + project.builds.find_by(id: params[:build_id]) if params[:build_id] + end + + def build_from_ref + if params[:ref] + project.builds_for(params[:build_name], params[:ref]).latest.first + end end def artifacts_file -- cgit v1.2.1 From ef833a220508f6f8a692b74e7fe593c68981d6f5 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 11 Jul 2016 18:51:23 +0800 Subject: Give latest succeeded one, don't give pending/running ones --- app/controllers/projects/artifacts_controller.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index c00295cd3b5..f71499be4f7 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -61,7 +61,9 @@ class Projects::ArtifactsController < Projects::ApplicationController def build_from_ref if params[:ref] - project.builds_for(params[:build_name], params[:ref]).latest.first + builds = project.builds_for(params[:build_name], params[:ref]) + + builds.latest.success.first end end -- cgit v1.2.1 From df5b78676e914ad8e14e96322b1dce383ae26875 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 11 Jul 2016 19:06:14 +0800 Subject: Using plain if/else is much easier to understand --- app/controllers/projects/artifacts_controller.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index f71499be4f7..944fde11b09 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -5,11 +5,11 @@ class Projects::ArtifactsController < Projects::ApplicationController before_action :validate_artifacts! def download - unless artifacts_file.file_storage? - return redirect_to artifacts_file.url + if artifacts_file.file_storage? + send_file artifacts_file.path, disposition: 'attachment' + else + redirect_to artifacts_file.url end - - send_file artifacts_file.path, disposition: 'attachment' end def browse -- cgit v1.2.1 From 1f733a95c73ca767287fcad180e4fa367b4a2354 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 11 Jul 2016 19:06:40 +0800 Subject: Remove redundant return --- app/controllers/projects/artifacts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 944fde11b09..7d6ba80b965 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -16,7 +16,7 @@ class Projects::ArtifactsController < Projects::ApplicationController directory = params[:path] ? "#{params[:path]}/" : '' @entry = build.artifacts_metadata_entry(directory) - return render_404 unless @entry.exists? + render_404 unless @entry.exists? end def file -- cgit v1.2.1 From 2bee8e7db927d2bc2c5912b98dfe52d3c3c40fbd Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Mon, 11 Jul 2016 13:50:45 +0100 Subject: Hide build spinner on canceled builds Closes #19651 --- app/assets/javascripts/ci/build.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/ci/build.coffee b/app/assets/javascripts/ci/build.coffee index 74691b2c1b5..26b8686dee8 100644 --- a/app/assets/javascripts/ci/build.coffee +++ b/app/assets/javascripts/ci/build.coffee @@ -46,13 +46,15 @@ class @CiBuild , 4000 getInitialBuildTrace: -> + removeRefreshStatuses = ['success', 'failed', 'canceled'] + $.ajax url: @build_url dataType: 'json' success: (build_data) -> $('.js-build-output').html build_data.trace_html - if build_data.status is 'success' or build_data.status is 'failed' + if removeRefreshStatuses.indexOf(build_data.status) >= 0 $('.js-build-refresh').remove() getBuildTrace: -> -- cgit v1.2.1 From d0451a050d5c4a3d343077d0820451af5058636b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 12 Jul 2016 18:56:41 +0800 Subject: Test for Project#builds_for and return empty array for nothing --- app/models/project.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index f3266a1b197..35ffb0a415d 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -430,6 +430,9 @@ class Project < ActiveRecord::Base end def builds_for(build_name, ref = 'HEAD') + ct = commit(ref) + return [] unless ct + sha = commit(ref).sha builds.joins(:pipeline). -- cgit v1.2.1 From 6597c213c341ae072216c125a97f94a174fc3dfa Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 12 Jul 2016 19:28:21 +0800 Subject: Prefer empty relation rather than arrays --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 35ffb0a415d..bc15f8c4138 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -431,7 +431,7 @@ class Project < ActiveRecord::Base def builds_for(build_name, ref = 'HEAD') ct = commit(ref) - return [] unless ct + return builds.none unless ct sha = commit(ref).sha -- cgit v1.2.1 From c94cff3e13d3f5ab55816ba2e84f48a659462441 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 12 Jul 2016 19:29:59 +0800 Subject: Prefer if over return --- app/models/project.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index bc15f8c4138..366817079bb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -431,13 +431,17 @@ class Project < ActiveRecord::Base def builds_for(build_name, ref = 'HEAD') ct = commit(ref) - return builds.none unless ct - sha = commit(ref).sha + if ct.nil? + builds.none - builds.joins(:pipeline). - merge(Ci::Pipeline.where(sha: sha)). - where(name: build_name) + else + sha = ct.sha + + builds.joins(:pipeline). + merge(Ci::Pipeline.where(sha: sha)). + where(name: build_name) + end end def merge_base_commit(first_commit_id, second_commit_id) -- cgit v1.2.1 From e383254070baf8a4701e3a10b7cc699f03cefff4 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 12 Jul 2016 23:15:08 +0800 Subject: Add all the tests and fix stuffs along the way: It turns out they are different: builds.success.latest.first and builds.latest.success.first If we put success first, that latest would also filter via success, and which is what we want here. --- app/controllers/projects/artifacts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 7d6ba80b965..25a1c2ca7e1 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -63,7 +63,7 @@ class Projects::ArtifactsController < Projects::ApplicationController if params[:ref] builds = project.builds_for(params[:build_name], params[:ref]) - builds.latest.success.first + builds.success.latest.first end end -- cgit v1.2.1 From 57c72cb0dfc980106163b313f850c5b8a5e31a70 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 12 Jul 2016 23:26:30 +0800 Subject: Could be faster when params[:path] is missing --- app/controllers/projects/artifacts_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 25a1c2ca7e1..bf9d72ae90c 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -36,9 +36,9 @@ class Projects::ArtifactsController < Projects::ApplicationController end def search - url = namespace_project_build_url(project.namespace, project, build) - if params[:path] + url = namespace_project_build_url(project.namespace, project, build) + redirect_to "#{url}/artifacts/#{params[:path]}" else render_404 -- cgit v1.2.1 From d0b9112fefcf0ee01d9df2dd9c2f1076738a53f1 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 12 Jul 2016 23:28:41 +0800 Subject: save some lines and a local variable --- app/models/project.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 366817079bb..2a9d68d10d2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -436,10 +436,8 @@ class Project < ActiveRecord::Base builds.none else - sha = ct.sha - builds.joins(:pipeline). - merge(Ci::Pipeline.where(sha: sha)). + merge(Ci::Pipeline.where(sha: ct.sha)). where(name: build_name) end end -- cgit v1.2.1 From bb5f06718cd4fb344398a5fef19f3cf9b400de97 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 13 Jul 2016 18:19:29 +0800 Subject: Rename to ref_name so it's aligning with API --- app/controllers/projects/artifacts_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index bf9d72ae90c..f1370efd64e 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -60,8 +60,8 @@ class Projects::ArtifactsController < Projects::ApplicationController end def build_from_ref - if params[:ref] - builds = project.builds_for(params[:build_name], params[:ref]) + if params[:ref_name] + builds = project.builds_for(params[:build_name], params[:ref_name]) builds.success.latest.first end -- cgit v1.2.1 From 66b91ce9ac70025093d52247ecfaa3f47536809f Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 14 Jul 2016 14:24:17 +0800 Subject: Avoid shadowing CommitStatus#id, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13047163 --- app/models/commit_status.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 6828705dbc8..baabbd785cc 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -17,11 +17,11 @@ class CommitStatus < ActiveRecord::Base alias_attribute :author, :user scope :latest, -> do - id = unscope(:select). + max_id = unscope(:select). select("max(#{table_name}.id)"). group(:name, :commit_id) - where(id: id) + where(id: max_id) end scope :retried, -> { where.not(id: latest) } scope :ordered, -> { order(:name) } -- cgit v1.2.1 From 5544852825d637dfe24b53e93b1e95d21767783c Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 14 Jul 2016 14:25:07 +0800 Subject: Remove blank line between if/else clause, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13047184 --- app/models/project.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 2a9d68d10d2..48bb9743439 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -434,7 +434,6 @@ class Project < ActiveRecord::Base if ct.nil? builds.none - else builds.joins(:pipeline). merge(Ci::Pipeline.where(sha: ct.sha)). -- cgit v1.2.1 From fab8bc5313a56c5f22e56903de2cb9c86df79fe4 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 14 Jul 2016 14:26:04 +0800 Subject: More descriptive local variable, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13047190 --- app/models/project.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 48bb9743439..793cf2d70fb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -430,13 +430,13 @@ class Project < ActiveRecord::Base end def builds_for(build_name, ref = 'HEAD') - ct = commit(ref) + commit_object = commit(ref) - if ct.nil? + if commit_object.nil? builds.none else builds.joins(:pipeline). - merge(Ci::Pipeline.where(sha: ct.sha)). + merge(Ci::Pipeline.where(sha: commit_object.sha)). where(name: build_name) end end -- cgit v1.2.1 From d7bbee7593ee54a9685c9eded00b121cca3913be Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 14 Jul 2016 16:45:46 +0800 Subject: Update routes based on feedback from: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13058785 And note that job/build_name could contain `/` --- app/controllers/projects/artifacts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index f1370efd64e..3e487c24cbd 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -61,7 +61,7 @@ class Projects::ArtifactsController < Projects::ApplicationController def build_from_ref if params[:ref_name] - builds = project.builds_for(params[:build_name], params[:ref_name]) + builds = project.builds_for(params[:job], params[:ref_name]) builds.success.latest.first end -- cgit v1.2.1 From 53a9dee6cb54b75fa2999b4a33a59928b3b73ec3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 15 Jul 2016 02:22:29 +0800 Subject: Introduce Project#latest_success_builds_for: So it's more accessible for views to access the names of jobs. Only filter Build#name from where we really need to download it. --- app/controllers/projects/artifacts_controller.rb | 4 ++-- app/models/project.rb | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 3e487c24cbd..1b3c4ec9bd8 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -61,9 +61,9 @@ class Projects::ArtifactsController < Projects::ApplicationController def build_from_ref if params[:ref_name] - builds = project.builds_for(params[:job], params[:ref_name]) + builds = project.latest_success_builds_for(params[:ref_name]) - builds.success.latest.first + builds.where(name: params[:job]).first end end diff --git a/app/models/project.rb b/app/models/project.rb index 793cf2d70fb..384841dbb9a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -429,15 +429,18 @@ class Project < ActiveRecord::Base repository.commit(ref) end - def builds_for(build_name, ref = 'HEAD') + def latest_success_builds_for(ref = 'HEAD') + builds_for(ref).success.latest + end + + def builds_for(ref = 'HEAD') commit_object = commit(ref) if commit_object.nil? builds.none else builds.joins(:pipeline). - merge(Ci::Pipeline.where(sha: commit_object.sha)). - where(name: build_name) + merge(Ci::Pipeline.where(sha: commit_object.sha)) end end -- cgit v1.2.1 From e313fd124225a0d89f3ad86a0cbb62b93c855898 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Sat, 16 Jul 2016 17:44:34 -0500 Subject: Add artifacts button --- app/views/projects/tags/_download.html.haml | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 8a11dbfa9f4..3f335b84c52 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -1,14 +1,32 @@ -%span.btn-group - = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'zip'), class: 'btn btn-default', rel: 'nofollow' do - %span Source code - %a.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown' } +.dropdown.inline + %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } + = icon('download') %span.caret %span.sr-only Select Archive Format %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } + %li.dropdown-header Source code %li = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'zip'), rel: 'nofollow' do %span Download zip %li = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz + - job_names = project.latest_success_builds_for('v8.9.6').pluck(:name) + %li.dropdown-header Artifacts + + + +-# +-# - artifacts = pipeline.builds.latest.select { |b| b.artifacts? } +-# - if artifacts.present? +-# .dropdown.inline.build-artifacts +-# %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} +-# = icon('download') +-# %b.caret +-# %ul.dropdown-menu.dropdown-menu-align-right +-# - artifacts.each do |build| +-# %li +-# = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do +-# = icon("download") +-# %span Download '#{build.name}' artifacts -- cgit v1.2.1 From faeaeda60e5601914338899f6b23b677d37a2ab5 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Sun, 17 Jul 2016 13:22:53 -0500 Subject: Add artifacts to tags --- app/views/projects/tags/_download.html.haml | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'app') diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 3f335b84c52..1f4c6c9ec08 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -12,21 +12,10 @@ %li = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - job_names = project.latest_success_builds_for('v8.9.6').pluck(:name) - %li.dropdown-header Artifacts - - - --# --# - artifacts = pipeline.builds.latest.select { |b| b.artifacts? } --# - if artifacts.present? --# .dropdown.inline.build-artifacts --# %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} --# = icon('download') --# %b.caret --# %ul.dropdown-menu.dropdown-menu-align-right --# - artifacts.each do |build| --# %li --# = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do --# = icon("download") --# %span Download '#{build.name}' artifacts + - artifacts = project.builds_for(ref).latest.with_artifacts + - if artifacts.any? + %li.dropdown-header Artifacts + - artifacts.each do |job| + %li + = link_to download_namespace_project_build_artifacts_path(project.namespace, project, job), rel: 'nofollow' do + %span Download '#{job.name}' -- cgit v1.2.1 From 5c28f16a01dd2c5f3e5b4e97d70ee3a9b0cdad3f Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Sun, 17 Jul 2016 19:04:45 -0500 Subject: Add artifacts download button on project page and branches page --- app/assets/stylesheets/framework/lists.scss | 4 ++++ app/views/projects/branches/_branch.html.haml | 15 +++++++++++++++ app/views/projects/buttons/_download.html.haml | 23 +++++++++++++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 2c40ec430ca..95a56ee0e95 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -157,6 +157,10 @@ ul.content-list { margin-right: 0; } } + + .artifacts-btn { + margin-right: 10px; + } } // When dragging a list item diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 4bd85061240..78b3de46f58 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -27,6 +27,21 @@ = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-default', method: :post, title: "Compare" do Compare + - artifacts = @project.builds_for(@repository.root_ref).latest.with_artifacts + - if artifacts.any? + .dropdown.inline.artifacts-btn + %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } + = icon('download') + %span.caret + %span.sr-only + Select Archive Format + %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } + %li.dropdown-header Artifacts + - artifacts.each do |job| + %li + = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do + %span Download '#{job.name}' + - if can_remove_branch?(@project, branch.name) = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-remove remove-row has-tooltip', title: "Delete branch", method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?", container: 'body' }, remote: true do = icon("trash-o") diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 58f43ecb5d5..c971420b16c 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -1,4 +1,23 @@ - unless @project.empty_repo? - if can? current_user, :download_code, @project - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), class: 'btn has-tooltip', data: {container: "body"}, rel: 'nofollow', title: "Download ZIP" do - = icon('download') + .dropdown.inline.btn-group + %button.btn{ 'data-toggle' => 'dropdown' } + = icon('download') + %span.caret + %span.sr-only + Select Archive Format + %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } + %li.dropdown-header Source code + %li + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), rel: 'nofollow' do + %span Download zip + %li + = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'tar.gz'), rel: 'nofollow' do + %span Download tar.gz + - artifacts = @project.builds_for(@ref).latest.with_artifacts + - if artifacts.any? + %li.dropdown-header Artifacts + - artifacts.each do |job| + %li + = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do + %span Download '#{job.name}' -- cgit v1.2.1 From 39c1cabf27da7a082f4e3da669da6b91393016d9 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Sun, 17 Jul 2016 19:11:00 -0500 Subject: Fix dropdown caret --- app/views/projects/buttons/_download.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index c971420b16c..f504d514963 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -3,7 +3,7 @@ .dropdown.inline.btn-group %button.btn{ 'data-toggle' => 'dropdown' } = icon('download') - %span.caret + = icon('caret-down') %span.sr-only Select Archive Format %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } -- cgit v1.2.1 From 78c37bdd773da9a41dc55e6915408ccae03186ff Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 13:39:53 +0800 Subject: Use find_by, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13125486 --- app/controllers/projects/artifacts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 1b3c4ec9bd8..bfe0781d735 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -63,7 +63,7 @@ class Projects::ArtifactsController < Projects::ApplicationController if params[:ref_name] builds = project.latest_success_builds_for(params[:ref_name]) - builds.where(name: params[:job]).first + builds.find_by(name: params[:job]) end end -- cgit v1.2.1 From 5c1f75e983c88d4c884a15e9f84550fd256fb07f Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 16:47:47 +0800 Subject: Use ci_commits.gl_project_id instead of ci_builds.gl_project_id: Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13125513 --- app/models/project.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 384841dbb9a..d6e37e66a8b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -437,10 +437,11 @@ class Project < ActiveRecord::Base commit_object = commit(ref) if commit_object.nil? - builds.none + Ci::Build.none else - builds.joins(:pipeline). - merge(Ci::Pipeline.where(sha: commit_object.sha)) + Ci::Build.joins(:pipeline). + merge(Ci::Pipeline.where(sha: commit_object.sha, + project: self)) end end -- cgit v1.2.1 From 85409a5a10d22bebbc54a9c7b7c76e7c0e11b208 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 20:10:50 +0800 Subject: Use ci_commits.ref (Pipeline#ref) to find builds --- app/models/project.rb | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index d6e37e66a8b..770ec1c8a68 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -434,15 +434,8 @@ class Project < ActiveRecord::Base end def builds_for(ref = 'HEAD') - commit_object = commit(ref) - - if commit_object.nil? - Ci::Build.none - else - Ci::Build.joins(:pipeline). - merge(Ci::Pipeline.where(sha: commit_object.sha, - project: self)) - end + Ci::Build.joins(:pipeline). + merge(Ci::Pipeline.where(ref: ref, project: self)) end def merge_base_commit(first_commit_id, second_commit_id) -- cgit v1.2.1 From af86b8c2c2b6fb08ea55eb89f1dd20aba81862ae Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 21:11:53 +0800 Subject: Latest success pipelines (rather than builds) --- app/models/ci/pipeline.rb | 8 ++++++++ app/models/commit_status.rb | 4 ++-- app/models/project.rb | 7 ++----- 3 files changed, 12 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index fa4071e2482..431a91004cd 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -18,6 +18,14 @@ module Ci after_touch :update_state after_save :keep_around_commits + scope :latest, -> do + max_id = unscope(:select). + select("max(#{table_name}.id)"). + group(:ref) + + where(id: max_id) + end + def self.truncate_sha(sha) sha[0...8] end diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index baabbd785cc..3e97fe68d4b 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -18,8 +18,8 @@ class CommitStatus < ActiveRecord::Base scope :latest, -> do max_id = unscope(:select). - select("max(#{table_name}.id)"). - group(:name, :commit_id) + select("max(#{table_name}.id)"). + group(:name, :commit_id) where(id: max_id) end diff --git a/app/models/project.rb b/app/models/project.rb index 770ec1c8a68..1578fe67581 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -430,12 +430,9 @@ class Project < ActiveRecord::Base end def latest_success_builds_for(ref = 'HEAD') - builds_for(ref).success.latest - end - - def builds_for(ref = 'HEAD') Ci::Build.joins(:pipeline). - merge(Ci::Pipeline.where(ref: ref, project: self)) + merge(pipelines.where(ref: ref).success.latest). + with_artifacts end def merge_base_commit(first_commit_id, second_commit_id) -- cgit v1.2.1 From e51d4a05b7195a98b48548c4c7260886f956b6d2 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 21:17:16 +0800 Subject: We should actually give latest success builds as well --- app/models/project.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 1578fe67581..d26aa8073e8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -432,7 +432,7 @@ class Project < ActiveRecord::Base def latest_success_builds_for(ref = 'HEAD') Ci::Build.joins(:pipeline). merge(pipelines.where(ref: ref).success.latest). - with_artifacts + with_artifacts.success.latest end def merge_base_commit(first_commit_id, second_commit_id) -- cgit v1.2.1 From dcb436f58f16b20094d126bf0eb9e3403905c7cc Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 22:07:26 +0800 Subject: Use Project#latest_success_builds_for --- app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/buttons/_download.html.haml | 2 +- app/views/projects/tags/_download.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 78b3de46f58..ced0380bb0b 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -27,7 +27,7 @@ = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-default', method: :post, title: "Compare" do Compare - - artifacts = @project.builds_for(@repository.root_ref).latest.with_artifacts + - artifacts = @project.latest_success_builds_for(@repository.root_ref) - if artifacts.any? .dropdown.inline.artifacts-btn %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index f504d514963..2eedc0d9a42 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -14,7 +14,7 @@ %li = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - artifacts = @project.builds_for(@ref).latest.with_artifacts + - artifacts = @project.latest_success_builds_for(@ref) - if artifacts.any? %li.dropdown-header Artifacts - artifacts.each do |job| diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 1f4c6c9ec08..4a8ef77ad8b 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -12,7 +12,7 @@ %li = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - artifacts = project.builds_for(ref).latest.with_artifacts + - artifacts = project.latest_success_builds_for(ref) - if artifacts.any? %li.dropdown-header Artifacts - artifacts.each do |job| -- cgit v1.2.1 From 72699d9719a269a82be6af0812d86d84733c77bd Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 23:16:29 +0800 Subject: Should be branch.name, not root ref --- app/views/projects/branches/_branch.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index ced0380bb0b..c2d7237f142 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -27,7 +27,7 @@ = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-default', method: :post, title: "Compare" do Compare - - artifacts = @project.latest_success_builds_for(@repository.root_ref) + - artifacts = @project.latest_success_builds_for(branch.name) - if artifacts.any? .dropdown.inline.artifacts-btn %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } -- cgit v1.2.1 From 57a78c37c72b2d697bc863ebfb84d3ca61ba9d7b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 23:17:43 +0800 Subject: Show notice if builds are not from latest pipeline --- app/models/ci/build.rb | 3 +++ app/models/project.rb | 12 +++++++--- app/views/projects/branches/_branch.html.haml | 32 +++++++++++++++----------- app/views/projects/buttons/_download.html.haml | 18 +++++++++------ app/views/projects/tags/_download.html.haml | 18 +++++++++------ 5 files changed, 52 insertions(+), 31 deletions(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index ffac3a22efc..9af04964b85 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -15,6 +15,9 @@ module Ci scope :with_artifacts, ->() { where.not(artifacts_file: nil) } scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } + scope :latest_success_with_artifacts, ->() do + with_artifacts.success.latest + end mount_uploader :artifacts_file, ArtifactUploader mount_uploader :artifacts_metadata, ArtifactUploader diff --git a/app/models/project.rb b/app/models/project.rb index 12851c5d0ec..77431c3f538 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -429,10 +429,16 @@ class Project < ActiveRecord::Base repository.commit(ref) end - def latest_success_builds_for(ref = 'HEAD') + # ref can't be HEAD or SHA, can only be branch/tag name + def latest_success_pipeline_for(ref = 'master') + pipelines.where(ref: ref).success.latest + end + + # ref can't be HEAD or SHA, can only be branch/tag name + def latest_success_builds_for(ref = 'master') Ci::Build.joins(:pipeline). - merge(pipelines.where(ref: ref).success.latest). - with_artifacts.success.latest + merge(latest_success_pipeline_for(ref)). + latest_success_with_artifacts end def merge_base_commit(first_commit_id, second_commit_id) diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index c2d7237f142..084a8474c4f 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -27,20 +27,24 @@ = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-default', method: :post, title: "Compare" do Compare - - artifacts = @project.latest_success_builds_for(branch.name) - - if artifacts.any? - .dropdown.inline.artifacts-btn - %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } - = icon('download') - %span.caret - %span.sr-only - Select Archive Format - %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } - %li.dropdown-header Artifacts - - artifacts.each do |job| - %li - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do - %span Download '#{job.name}' + - pipeline = @project.latest_success_pipeline_for(branch.name).first + - if pipeline + - artifacts = pipeline.builds.latest_success_with_artifacts + - if artifacts.any? + .dropdown.inline.artifacts-btn + %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } + = icon('download') + %span.caret + %span.sr-only + Select Archive Format + %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } + %li.dropdown-header Artifacts + - unless pipeline.latest? + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_commits_path(@project.namespace, @project, pipeline.sha))})" + - artifacts.each do |job| + %li + = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do + %span Download '#{job.name}' - if can_remove_branch?(@project, branch.name) = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-remove remove-row has-tooltip', title: "Delete branch", method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?", container: 'body' }, remote: true do diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 2eedc0d9a42..24a11005e61 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -14,10 +14,14 @@ %li = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - artifacts = @project.latest_success_builds_for(@ref) - - if artifacts.any? - %li.dropdown-header Artifacts - - artifacts.each do |job| - %li - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do - %span Download '#{job.name}' + - pipeline = @project.latest_success_pipeline_for(@ref).first + - if pipeline + - artifacts = pipeline.builds.latest_success_with_artifacts + - if artifacts.any? + %li.dropdown-header Artifacts + - unless pipeline.latest? + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_commits_path(@project.namespace, @project, pipeline.sha))})" + - artifacts.each do |job| + %li + = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do + %span Download '#{job.name}' diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 4a8ef77ad8b..d2650809a3e 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -12,10 +12,14 @@ %li = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - artifacts = project.latest_success_builds_for(ref) - - if artifacts.any? - %li.dropdown-header Artifacts - - artifacts.each do |job| - %li - = link_to download_namespace_project_build_artifacts_path(project.namespace, project, job), rel: 'nofollow' do - %span Download '#{job.name}' + - pipeline = project.latest_success_pipeline_for(ref).first + - if pipeline + - artifacts = pipeline.builds.latest_success_with_artifacts + - if artifacts.any? + %li.dropdown-header Artifacts + - unless pipeline.latest? + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_commits_path(project.namespace, project, pipeline.sha))})" + - artifacts.each do |job| + %li + = link_to download_namespace_project_build_artifacts_path(project.namespace, project, job), rel: 'nofollow' do + %span Download '#{job.name}' -- cgit v1.2.1 From 914336b2d9da688a7b6267425a408c0ce280f9b2 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 23:26:30 +0800 Subject: Links to search_namespace_project_artifacts_path instead --- app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/buttons/_download.html.haml | 2 +- app/views/projects/tags/_download.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 084a8474c4f..bb1f2ec9604 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -43,7 +43,7 @@ = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_commits_path(@project.namespace, @project, pipeline.sha))})" - artifacts.each do |job| %li - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do + = link_to search_namespace_project_artifacts_path(@project.namespace, @project, branch.name, 'download', job: job.name), rel: 'nofollow' do %span Download '#{job.name}' - if can_remove_branch?(@project, branch.name) diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 24a11005e61..558a9023ed2 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -23,5 +23,5 @@ = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_commits_path(@project.namespace, @project, pipeline.sha))})" - artifacts.each do |job| %li - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do + = link_to search_namespace_project_artifacts_path(@project.namespace, @project, @ref, 'download', job: job.name), rel: 'nofollow' do %span Download '#{job.name}' diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index d2650809a3e..2a8891e917f 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -21,5 +21,5 @@ = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_commits_path(project.namespace, project, pipeline.sha))})" - artifacts.each do |job| %li - = link_to download_namespace_project_build_artifacts_path(project.namespace, project, job), rel: 'nofollow' do + = link_to search_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do %span Download '#{job.name}' -- cgit v1.2.1 From e00fb385b247f90f12ddadd090e87cd59f2ebb36 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Mon, 18 Jul 2016 23:34:31 +0800 Subject: Actually should use tree path --- app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/buttons/_download.html.haml | 2 +- app/views/projects/tags/_download.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index bb1f2ec9604..cbd6ab74128 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -40,7 +40,7 @@ %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_commits_path(@project.namespace, @project, pipeline.sha))})" + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_tree_path(@project.namespace, @project, pipeline.sha))})" - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(@project.namespace, @project, branch.name, 'download', job: job.name), rel: 'nofollow' do diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 558a9023ed2..f96045e09f0 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -20,7 +20,7 @@ - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_commits_path(@project.namespace, @project, pipeline.sha))})" + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_tree_path(@project.namespace, @project, pipeline.sha))})" - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(@project.namespace, @project, @ref, 'download', job: job.name), rel: 'nofollow' do diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 2a8891e917f..6a431bcf7b2 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -18,7 +18,7 @@ - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_commits_path(project.namespace, project, pipeline.sha))})" + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_tree_path(project.namespace, project, pipeline.sha))})" - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do -- cgit v1.2.1 From 5fa6af05eb42feed7e0ca69778019805f7780ea5 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Mon, 18 Jul 2016 21:02:18 -0700 Subject: Add artifacts to view branch page download dropdown --- .../repositories/_download_archive.html.haml | 29 ++++++++++------------ app/views/projects/tree/show.html.haml | 2 +- 2 files changed, 14 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index 24658319060..5b2ddce3e91 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -1,16 +1,14 @@ - ref = ref || nil - btn_class = btn_class || '' -- split_button = split_button || false -- if split_button == true - %span.btn-group{class: btn_class} - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn col-xs-10', rel: 'nofollow' do - %i.fa.fa-download - %span Download zip - %a.col-xs-2.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } +%span.btn-group{class: btn_class} + .dropdown.inline + %button.btn{ 'data-toggle' => 'dropdown' } + = icon('download') %span.caret %span.sr-only Select Archive Format - %ul.col-xs-10.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } + %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } + %li.dropdown-header Source code %li = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), rel: 'nofollow' do %i.fa.fa-download @@ -27,11 +25,10 @@ = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar'), rel: 'nofollow' do %i.fa.fa-download %span Download tar -- else - %span.btn-group{class: btn_class} - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), class: 'btn', rel: 'nofollow' do - %i.fa.fa-download - %span zip - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar.gz'), class: 'btn', rel: 'nofollow' do - %i.fa.fa-download - %span tar.gz + - artifacts = @project.latest_success_builds_for(@ref) + - if artifacts.any? + %li.dropdown-header Artifacts + - artifacts.each do |job| + %li + = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do + %span Download '#{job.name}' diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index bf5360b4dee..c68f86f1378 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -11,7 +11,7 @@ .tree-controls = render 'projects/find_file_link' - if can? current_user, :download_code, @project - = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'hidden-xs hidden-sm btn-grouped', split_button: true + = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'hidden-xs hidden-sm btn-grouped' #tree-holder.tree-holder.clearfix .nav-block -- cgit v1.2.1 From 1a41cb90175ac8d6f780bf4fd35e4862f5312574 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 19 Jul 2016 16:50:53 +0800 Subject: Fix links and add not latest notice --- .../projects/repositories/_download_archive.html.haml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index 5b2ddce3e91..396fb8598ae 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -25,10 +25,14 @@ = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar'), rel: 'nofollow' do %i.fa.fa-download %span Download tar - - artifacts = @project.latest_success_builds_for(@ref) - - if artifacts.any? - %li.dropdown-header Artifacts - - artifacts.each do |job| - %li - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, job), rel: 'nofollow' do - %span Download '#{job.name}' + - pipeline = @project.latest_success_pipeline_for(ref).first + - if pipeline + - artifacts = pipeline.builds.latest_success_with_artifacts + - if artifacts.any? + %li.dropdown-header Artifacts + - unless pipeline.latest? + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_tree_path(@project.namespace, @project, pipeline.sha))})" + - artifacts.each do |job| + %li + = link_to search_namespace_project_artifacts_path(@project.namespace, @project, ref, 'download', job: job.name), rel: 'nofollow' do + %span Download '#{job.name}' -- cgit v1.2.1 From fba2ec45b3bf493611f2d7e7e13a21c39bc654e0 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 19 Jul 2016 17:08:21 +0800 Subject: Just use order(id: :desc) for latest stuffs: We don't need that subquery for group by ref and alike here. --- app/models/ci/build.rb | 2 +- app/models/ci/pipeline.rb | 10 +--------- app/models/project.rb | 2 +- 3 files changed, 3 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 9af04964b85..c048eff0f80 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -16,7 +16,7 @@ module Ci scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } scope :latest_success_with_artifacts, ->() do - with_artifacts.success.latest + with_artifacts.success.order(id: :desc) end mount_uploader :artifacts_file, ArtifactUploader diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index a8e6a23e1c4..148b056789a 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -20,14 +20,6 @@ module Ci after_touch :update_state after_save :keep_around_commits - scope :latest, -> do - max_id = unscope(:select). - select("max(#{table_name}.id)"). - group(:ref) - - where(id: max_id) - end - def self.truncate_sha(sha) sha[0...8] end @@ -226,7 +218,7 @@ module Ci def keep_around_commits return unless project - + project.repository.keep_around(self.sha) project.repository.keep_around(self.before_sha) end diff --git a/app/models/project.rb b/app/models/project.rb index 77431c3f538..30e8ade99ff 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -431,7 +431,7 @@ class Project < ActiveRecord::Base # ref can't be HEAD or SHA, can only be branch/tag name def latest_success_pipeline_for(ref = 'master') - pipelines.where(ref: ref).success.latest + pipelines.where(ref: ref).success.order(id: :desc) end # ref can't be HEAD or SHA, can only be branch/tag name -- cgit v1.2.1 From 0538e1e934484e76575164314fe8451374e4a4c8 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 19 Jul 2016 17:09:32 +0800 Subject: Support SHA for downloading artifacts: So if we also query against SHA, we could actually support SHA. If there's a branch or tag also named like SHA this could be ambiguous, but since we could already do that in Git, I think it's probably fine, people would be aware they shouldn't use the same name anyway. --- app/models/project.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 30e8ade99ff..c1cb1558132 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -429,12 +429,15 @@ class Project < ActiveRecord::Base repository.commit(ref) end - # ref can't be HEAD or SHA, can only be branch/tag name + # ref can't be HEAD, can only be branch/tag name or SHA def latest_success_pipeline_for(ref = 'master') - pipelines.where(ref: ref).success.order(id: :desc) + table = Ci::Pipeline.quoted_table_name + # TODO: Use `where(ref: ref).or(sha: ref)` in Rails 5 + pipelines.where("#{table}.ref = ? OR #{table}.sha = ?", ref, ref). + success.order(id: :desc) end - # ref can't be HEAD or SHA, can only be branch/tag name + # ref can't be HEAD, can only be branch/tag name or SHA def latest_success_builds_for(ref = 'master') Ci::Build.joins(:pipeline). merge(latest_success_pipeline_for(ref)). -- cgit v1.2.1 From 85ceb8b72f5a67d21bc9530fe835fdece98f3d4e Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 19 Jul 2016 17:51:45 +0800 Subject: Rename latest_success* to latest_successful: Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13164642 --- app/controllers/projects/artifacts_controller.rb | 2 +- app/models/ci/build.rb | 2 +- app/models/project.rb | 8 ++++---- app/views/projects/branches/_branch.html.haml | 4 ++-- app/views/projects/buttons/_download.html.haml | 4 ++-- app/views/projects/repositories/_download_archive.html.haml | 4 ++-- app/views/projects/tags/_download.html.haml | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index f33cf238d88..05112571225 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -60,7 +60,7 @@ class Projects::ArtifactsController < Projects::ApplicationController def build_from_ref if params[:ref_name] - builds = project.latest_success_builds_for(params[:ref_name]) + builds = project.latest_successful_builds_for(params[:ref_name]) builds.find_by(name: params[:job]) end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index c048eff0f80..65dfe4f0190 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -15,7 +15,7 @@ module Ci scope :with_artifacts, ->() { where.not(artifacts_file: nil) } scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } - scope :latest_success_with_artifacts, ->() do + scope :latest_successful_with_artifacts, ->() do with_artifacts.success.order(id: :desc) end diff --git a/app/models/project.rb b/app/models/project.rb index c1cb1558132..60928bf9922 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -430,7 +430,7 @@ class Project < ActiveRecord::Base end # ref can't be HEAD, can only be branch/tag name or SHA - def latest_success_pipeline_for(ref = 'master') + def latest_successful_pipeline_for(ref = 'master') table = Ci::Pipeline.quoted_table_name # TODO: Use `where(ref: ref).or(sha: ref)` in Rails 5 pipelines.where("#{table}.ref = ? OR #{table}.sha = ?", ref, ref). @@ -438,10 +438,10 @@ class Project < ActiveRecord::Base end # ref can't be HEAD, can only be branch/tag name or SHA - def latest_success_builds_for(ref = 'master') + def latest_successful_builds_for(ref = 'master') Ci::Build.joins(:pipeline). - merge(latest_success_pipeline_for(ref)). - latest_success_with_artifacts + merge(latest_successful_pipeline_for(ref)). + latest_successful_with_artifacts end def merge_base_commit(first_commit_id, second_commit_id) diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index cbd6ab74128..8f6ddfd9044 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -27,9 +27,9 @@ = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-default', method: :post, title: "Compare" do Compare - - pipeline = @project.latest_success_pipeline_for(branch.name).first + - pipeline = @project.latest_successful_pipeline_for(branch.name).first - if pipeline - - artifacts = pipeline.builds.latest_success_with_artifacts + - artifacts = pipeline.builds.latest_successful_with_artifacts - if artifacts.any? .dropdown.inline.artifacts-btn %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index f96045e09f0..047931a7fa5 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -14,9 +14,9 @@ %li = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - pipeline = @project.latest_success_pipeline_for(@ref).first + - pipeline = @project.latest_successful_pipeline_for(@ref).first - if pipeline - - artifacts = pipeline.builds.latest_success_with_artifacts + - artifacts = pipeline.builds.latest_successful_with_artifacts - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index 396fb8598ae..1c03aa0a332 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -25,9 +25,9 @@ = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar'), rel: 'nofollow' do %i.fa.fa-download %span Download tar - - pipeline = @project.latest_success_pipeline_for(ref).first + - pipeline = @project.latest_successful_pipeline_for(ref).first - if pipeline - - artifacts = pipeline.builds.latest_success_with_artifacts + - artifacts = pipeline.builds.latest_successful_with_artifacts - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 6a431bcf7b2..8e5e5cb559b 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -12,9 +12,9 @@ %li = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - pipeline = project.latest_success_pipeline_for(ref).first + - pipeline = project.latest_successful_pipeline_for(ref).first - if pipeline - - artifacts = pipeline.builds.latest_success_with_artifacts + - artifacts = pipeline.builds.latest_successful_with_artifacts - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? -- cgit v1.2.1 From e3ce02300bf90451b98479720d1093afe8b7eea8 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 19 Jul 2016 18:03:21 +0800 Subject: Link to pipeline instead of source tree, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13164795 --- app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/buttons/_download.html.haml | 2 +- app/views/projects/repositories/_download_archive.html.haml | 2 +- app/views/projects/tags/_download.html.haml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 8f6ddfd9044..e48b78f9eef 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -40,7 +40,7 @@ %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_tree_path(@project.namespace, @project, pipeline.sha))})" + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_pipeline_path(@project.namespace, @project, pipeline))})" - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(@project.namespace, @project, branch.name, 'download', job: job.name), rel: 'nofollow' do diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 047931a7fa5..32f911f6b31 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -20,7 +20,7 @@ - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_tree_path(@project.namespace, @project, pipeline.sha))})" + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_pipeline_path(@project.namespace, @project, pipeline))})" - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(@project.namespace, @project, @ref, 'download', job: job.name), rel: 'nofollow' do diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index 1c03aa0a332..e29d99371c8 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -31,7 +31,7 @@ - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_tree_path(@project.namespace, @project, pipeline.sha))})" + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_pipeline_path(@project.namespace, @project, pipeline))})" - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(@project.namespace, @project, ref, 'download', job: job.name), rel: 'nofollow' do diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 8e5e5cb559b..8acf145049a 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -18,7 +18,7 @@ - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_tree_path(project.namespace, project, pipeline.sha))})" + = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_pipeline_path(project.namespace, project, pipeline))})" - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do -- cgit v1.2.1 From 2afcc9e910bde32507e14be452c9f7681f5497e4 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Jul 2016 14:10:21 +0300 Subject: Create new version of merge request diff on push instead of updating existing one Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index f1b9c1d6feb..ef0b7da048e 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -10,8 +10,7 @@ class MergeRequest < ActiveRecord::Base belongs_to :source_project, foreign_key: :source_project_id, class_name: "Project" belongs_to :merge_user, class_name: "User" - has_one :merge_request_diff, dependent: :destroy - + has_many :merge_request_diffs, dependent: :destroy has_many :events, as: :target, dependent: :destroy serialize :merge_params, Hash @@ -294,7 +293,9 @@ class MergeRequest < ActiveRecord::Base end def reload_diff - return unless merge_request_diff && open? + return unless open? + + merge_request_diff = merge_request_diffs.create old_diff_refs = self.diff_refs @@ -691,4 +692,8 @@ class MergeRequest < ActiveRecord::Base def keep_around_commit project.repository.keep_around(self.merge_commit_sha) end + + def merge_request_diff + merge_request_diffs.first + end end -- cgit v1.2.1 From ceff8106433187613eb97d13952fc96c4806b847 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Jul 2016 17:04:55 +0300 Subject: Create merge request diff on merge request creation Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index ef0b7da048e..88c5987d485 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -286,6 +286,10 @@ class MergeRequest < ActiveRecord::Base end end + def create_merge_request_diff + merge_request_diffs.create + end + def update_merge_request_diff if source_branch_changed? || target_branch_changed? reload_diff -- cgit v1.2.1 From 94ca25c9b8c62f9995fbd571c33954754950e1da Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 25 Jul 2016 18:42:57 +0300 Subject: Improve merge request diff creation and update tests Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 88c5987d485..cc1d0c18437 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -299,12 +299,8 @@ class MergeRequest < ActiveRecord::Base def reload_diff return unless open? - merge_request_diff = merge_request_diffs.create - old_diff_refs = self.diff_refs - - merge_request_diff.reload_content - + create_merge_request_diff new_diff_refs = self.diff_refs update_diff_notes_positions( -- cgit v1.2.1 From b8fef7eb5948344f4d442a52637cad168f4c5bf1 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Jul 2016 18:24:25 +0300 Subject: Add ability to render different merge request versions Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/merge_requests_controller.rb | 8 +++++++- app/models/merge_request_diff.rb | 10 ++++++++++ .../projects/merge_requests/show/_diffs.html.haml | 5 +++-- .../projects/merge_requests/show/_versions.html.haml | 18 ++++++++++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 app/views/projects/merge_requests/show/_versions.html.haml (limited to 'app') diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 03166294ddd..a886af713d5 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -81,7 +81,13 @@ class Projects::MergeRequestsController < Projects::ApplicationController def diffs apply_diff_view_cookie! - @merge_request_diff = @merge_request.merge_request_diff + @merge_request_diff = + if params[:diff_id] + @merge_request.merge_request_diffs.find(params[:diff_id]) + else + @merge_request.merge_request_diff + end + respond_to do |format| format.html { define_discussion_vars } diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 3f520c8f3ff..a92f597225a 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -96,6 +96,16 @@ class MergeRequestDiff < ActiveRecord::Base end end + def diff_refs + return unless start_commit || base_commit + + Gitlab::Diff::DiffRefs.new( + base_sha: base_commit_sha, + start_sha: start_commit_sha, + head_sha: head_commit_sha + ) + end + private # Collect array of Git::Commit objects diff --git a/app/views/projects/merge_requests/show/_diffs.html.haml b/app/views/projects/merge_requests/show/_diffs.html.haml index 1b0bae86ad4..e26499cc144 100644 --- a/app/views/projects/merge_requests/show/_diffs.html.haml +++ b/app/views/projects/merge_requests/show/_diffs.html.haml @@ -1,6 +1,7 @@ - if @merge_request_diff.collected? - = render "projects/diffs/diffs", diffs: @merge_request.diffs(diff_options), - project: @merge_request.project, diff_refs: @merge_request.diff_refs + = render 'projects/merge_requests/show/versions' + = render "projects/diffs/diffs", diffs: @merge_request_diff.diffs(diff_options), + project: @merge_request.project, diff_refs: @merge_request_diff.diff_refs - elsif @merge_request_diff.empty? .nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch} - else diff --git a/app/views/projects/merge_requests/show/_versions.html.haml b/app/views/projects/merge_requests/show/_versions.html.haml new file mode 100644 index 00000000000..2764786d9bf --- /dev/null +++ b/app/views/projects/merge_requests/show/_versions.html.haml @@ -0,0 +1,18 @@ +- if @merge_request.merge_request_diffs.size > 1 + - latest_diff = @merge_request.merge_request_diff + .light-well + Merge Request version + + %span.dropdown.inline + %a.dropdown-toggle{ data: {toggle: :dropdown} } + %strong.monospace #{@merge_request_diff.base_commit.short_id}..#{@merge_request_diff.head_commit.short_id} + %span.caret + %ul.dropdown-menu + - @merge_request.merge_request_diffs.each do |merge_request_diff| + %li{ class: ('active' if merge_request_diff == latest_diff) } + = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request, diff_id: merge_request_diff.id) do + %strong.monospace + #{merge_request_diff.base_commit.short_id}..#{merge_request_diff.head_commit.short_id} + %br + %small + = time_ago_with_tooltip(merge_request_diff.created_at) -- cgit v1.2.1 From dbd58dc4bb638be33f98336410ae6f4ede15f737 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 26 Jul 2016 20:03:45 +0300 Subject: Improve merge request version switcher Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/framework/dropdowns.scss | 6 ++++++ app/assets/stylesheets/pages/merge_requests.scss | 6 ++++++ .../merge_requests/show/_versions.html.haml | 24 ++++++++++++++-------- 3 files changed, 27 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index c54eb0d6479..28346423541 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -17,6 +17,12 @@ .dropdown { position: relative; + + .btn-link { + &:hover { + cursor: pointer; + } + } } .open { diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 0a661e529f0..14ded0eec72 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -371,3 +371,9 @@ } } } + +.mr-version-switch { + background: $background-color; + padding: $gl-btn-padding; + border-bottom: 1px solid $border-color; +} diff --git a/app/views/projects/merge_requests/show/_versions.html.haml b/app/views/projects/merge_requests/show/_versions.html.haml index 2764786d9bf..5c0098bcf98 100644 --- a/app/views/projects/merge_requests/show/_versions.html.haml +++ b/app/views/projects/merge_requests/show/_versions.html.haml @@ -1,18 +1,24 @@ -- if @merge_request.merge_request_diffs.size > 1 - - latest_diff = @merge_request.merge_request_diff - .light-well - Merge Request version +- diffs_count = @merge_request.merge_request_diffs.count +- if diffs_count > 1 + - latest_diff = @merge_request.merge_request_diff + .mr-version-switch + Version:  %span.dropdown.inline - %a.dropdown-toggle{ data: {toggle: :dropdown} } - %strong.monospace #{@merge_request_diff.base_commit.short_id}..#{@merge_request_diff.head_commit.short_id} + %a.btn-link.dropdown-toggle{ data: {toggle: :dropdown} } + %strong.monospace< + - if latest_diff == @merge_request_diff + #{"latest"} + - else + #{@merge_request_diff.base_commit.short_id}..#{@merge_request_diff.head_commit.short_id} %span.caret - %ul.dropdown-menu + %ul.dropdown-menu.dropdown-menu-selectable - @merge_request.merge_request_diffs.each do |merge_request_diff| - %li{ class: ('active' if merge_request_diff == latest_diff) } - = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request, diff_id: merge_request_diff.id) do + %li + = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request, diff_id: merge_request_diff.id), class: ('is-active' if merge_request_diff == @merge_request_diff) do %strong.monospace #{merge_request_diff.base_commit.short_id}..#{merge_request_diff.head_commit.short_id} %br %small + = time_ago_with_tooltip(merge_request_diff.created_at) -- cgit v1.2.1 From 6190216541adb04fd0ce4b21862e6b253b868671 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Jul 2016 11:27:06 +0300 Subject: Add small visual improvements to merge request version switch Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/pages/merge_requests.scss | 6 +++++- app/views/projects/merge_requests/show/_versions.html.haml | 9 ++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 14ded0eec72..7d8f58ca5af 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -375,5 +375,9 @@ .mr-version-switch { background: $background-color; padding: $gl-btn-padding; - border-bottom: 1px solid $border-color; + color: $gl-placeholder-color; + + a.btn-link { + color: $gl-dark-link-color; + } } diff --git a/app/views/projects/merge_requests/show/_versions.html.haml b/app/views/projects/merge_requests/show/_versions.html.haml index 5c0098bcf98..8b7d866941c 100644 --- a/app/views/projects/merge_requests/show/_versions.html.haml +++ b/app/views/projects/merge_requests/show/_versions.html.haml @@ -10,15 +10,18 @@ - if latest_diff == @merge_request_diff #{"latest"} - else - #{@merge_request_diff.base_commit.short_id}..#{@merge_request_diff.head_commit.short_id} + #{@merge_request_diff.head_commit.short_id} %span.caret %ul.dropdown-menu.dropdown-menu-selectable - @merge_request.merge_request_diffs.each do |merge_request_diff| %li = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request, diff_id: merge_request_diff.id), class: ('is-active' if merge_request_diff == @merge_request_diff) do %strong.monospace - #{merge_request_diff.base_commit.short_id}..#{merge_request_diff.head_commit.short_id} + #{merge_request_diff.head_commit.short_id} %br %small - = time_ago_with_tooltip(merge_request_diff.created_at) + + .pull-right + %span.monospace + git diff #{@merge_request_diff.base_commit.short_id}..#{@merge_request_diff.head_commit.short_id} -- cgit v1.2.1 From 09fa0139281d7a76d6b40991f7672187fea40e67 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 27 Jul 2016 14:41:19 +0300 Subject: Refactor merge request diff Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 89 +++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 51 deletions(-) (limited to 'app') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index a92f597225a..07bceda049c 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -8,7 +8,8 @@ class MergeRequestDiff < ActiveRecord::Base belongs_to :merge_request - delegate :source_branch_sha, :target_branch_sha, :target_branch, :source_branch, to: :merge_request, prefix: nil + delegate :source_branch_sha, :target_branch_sha, + :target_branch, :source_branch, to: :merge_request, prefix: nil state_machine :state, initial: :empty do state :collected @@ -24,9 +25,16 @@ class MergeRequestDiff < ActiveRecord::Base serialize :st_commits serialize :st_diffs + after_initialize :set_diff_range after_create :reload_content, unless: :importing? after_save :keep_around_commits, unless: :importing? + def set_diff_range + self.start_commit_sha ||= target_branch_sha + self.head_commit_sha ||= source_branch_sha + self.base_commit_sha ||= branch_base_sha + end + def reload_content reload_commits reload_diffs @@ -41,8 +49,8 @@ class MergeRequestDiff < ActiveRecord::Base @diffs_no_whitespace ||= begin compare = Gitlab::Git::Compare.new( repository.raw_repository, - self.start_commit_sha || self.target_branch_sha, - self.head_commit_sha || self.source_branch_sha, + start_commit_sha, + head_commit_sha ) compare.diffs(options) end @@ -65,35 +73,21 @@ class MergeRequestDiff < ActiveRecord::Base end def base_commit - return unless self.base_commit_sha + return unless base_commit_sha - project.commit(self.base_commit_sha) + project.commit(base_commit_sha) end def start_commit - return unless self.start_commit_sha + return unless start_commit_sha - project.commit(self.start_commit_sha) + project.commit(start_commit_sha) end def head_commit - return last_commit unless self.head_commit_sha + return last_commit unless head_commit_sha - project.commit(self.head_commit_sha) - end - - def compare - @compare ||= - begin - # Update ref for merge request - merge_request.fetch_ref - - Gitlab::Git::Compare.new( - repository.raw_repository, - self.target_branch_sha, - self.source_branch_sha - ) - end + project.commit(head_commit_sha) end def diff_refs @@ -108,16 +102,18 @@ class MergeRequestDiff < ActiveRecord::Base private - # Collect array of Git::Commit objects - # between target and source branches - def unmerged_commits - commits = compare.commits - - if commits.present? - commits = Commit.decorate(commits, merge_request.source_project).reverse - end + def compare + @compare ||= + begin + # Update ref for merge request + merge_request.fetch_ref - commits + Gitlab::Git::Compare.new( + repository.raw_repository, + start_commit_sha, + head_commit_sha + ) + end end def dump_commits(commits) @@ -133,21 +129,16 @@ class MergeRequestDiff < ActiveRecord::Base def reload_commits new_attributes = {} - commit_objects = unmerged_commits + commits = compare.commits - if commit_objects.present? - new_attributes[:st_commits] = dump_commits(commit_objects) + if commits.present? + commits = Commit.decorate(commits, merge_request.source_project).reverse + new_attributes[:st_commits] = dump_commits(commits) end update_columns_serialized(new_attributes) end - # Collect array of Git::Diff objects - # between target and source branches - def unmerged_diffs - compare.diffs(Commit.max_diff_options) - end - def dump_diffs(diffs) if diffs.respond_to?(:map) diffs.map(&:to_hash) @@ -177,7 +168,7 @@ class MergeRequestDiff < ActiveRecord::Base if commits.size.zero? new_attributes[:state] = :empty else - diff_collection = unmerged_diffs + diff_collection = compare.diffs(Commit.max_diff_options) if diff_collection.overflow? # Set our state to 'overflow' to make the #empty? and #collected? @@ -195,10 +186,6 @@ class MergeRequestDiff < ActiveRecord::Base new_attributes[:st_diffs] = new_diffs - new_attributes[:start_commit_sha] = self.target_branch_sha - new_attributes[:head_commit_sha] = self.source_branch_sha - new_attributes[:base_commit_sha] = branch_base_sha - update_columns_serialized(new_attributes) keep_around_commits @@ -213,9 +200,9 @@ class MergeRequestDiff < ActiveRecord::Base end def branch_base_commit - return unless self.source_branch_sha && self.target_branch_sha + return unless source_branch_sha && target_branch_sha - project.merge_base_commit(self.source_branch_sha, self.target_branch_sha) + project.merge_base_commit(source_branch_sha, target_branch_sha) end def branch_base_sha @@ -254,8 +241,8 @@ class MergeRequestDiff < ActiveRecord::Base end def keep_around_commits - repository.keep_around(target_branch_sha) - repository.keep_around(source_branch_sha) - repository.keep_around(branch_base_sha) + repository.keep_around(start_commit_sha) + repository.keep_around(head_commit_sha) + repository.keep_around(base_commit_sha) end end -- cgit v1.2.1 From 988836bc807a6e7ba5362fd8bddd330d1f3bf19b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Jul 2016 11:36:30 +0300 Subject: Refactor MergeRequestDiff model Since MergeRequestDiff is not about branches and current state of merge request diff anymore I removed most of branch related method and added validation for head/start/base commit sha. From this point MergeRequestDiff is about saving diff between branches only once at moment of creation. Once created MergeRequestDiff should not be changes. Because of that we should not rely on changes in source/target branches when read from MergeRequestDiff Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'app') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 07bceda049c..1e529c84706 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -8,9 +8,6 @@ class MergeRequestDiff < ActiveRecord::Base belongs_to :merge_request - delegate :source_branch_sha, :target_branch_sha, - :target_branch, :source_branch, to: :merge_request, prefix: nil - state_machine :state, initial: :empty do state :collected state :overflow @@ -25,14 +22,23 @@ class MergeRequestDiff < ActiveRecord::Base serialize :st_commits serialize :st_diffs - after_initialize :set_diff_range - after_create :reload_content, unless: :importing? + validates :head_commit_sha, presence: true + validates :start_commit_sha, presence: true + validates :base_commit_sha, presence: true + + after_initialize :ensure_head_commit_sha, if: :persisted? + before_create :set_diff_range, unless: :importing? + after_create :reload_content, unless: :importing? after_save :keep_around_commits, unless: :importing? + def ensure_head_commit_sha + self.head_commit_sha ||= last_commit.sha + end + def set_diff_range - self.start_commit_sha ||= target_branch_sha - self.head_commit_sha ||= source_branch_sha - self.base_commit_sha ||= branch_base_sha + self.start_commit_sha ||= merge_request.target_branch_sha + self.head_commit_sha ||= merge_request.source_branch_sha + self.base_commit_sha ||= find_base_sha end def reload_content @@ -199,14 +205,10 @@ class MergeRequestDiff < ActiveRecord::Base project.repository end - def branch_base_commit - return unless source_branch_sha && target_branch_sha - - project.merge_base_commit(source_branch_sha, target_branch_sha) - end + def find_base_sha + return unless head_commit_sha && start_commit_sha - def branch_base_sha - branch_base_commit.try(:sha) + project.merge_base_commit(head_commit_sha, start_commit_sha).try(:sha) end def utf8_st_diffs -- cgit v1.2.1 From 964742f600f5fc5e07272982c4d3847ccc76ce00 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Jul 2016 13:46:27 +0300 Subject: Ensure merge request is created with valid diff object * Add merge_request_diff validation to merge_request model * Improve initialize of merge_request_diff object * Rename some merge_request_diff methods for clarity Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 7 ++++++- app/models/merge_request_diff.rb | 41 +++++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 20 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index cc1d0c18437..618829891a0 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -15,7 +15,7 @@ class MergeRequest < ActiveRecord::Base serialize :merge_params, Hash - after_create :create_merge_request_diff, unless: :importing? + before_validation :ensure_merge_request_diff, on: :create, unless: :importing? after_update :update_merge_request_diff delegate :commits, :real_size, to: :merge_request_diff, prefix: nil @@ -95,6 +95,7 @@ class MergeRequest < ActiveRecord::Base validates :merge_user, presence: true, if: :merge_when_build_succeeds? validate :validate_branches, unless: [:allow_broken, :importing?] validate :validate_fork + validates_associated :merge_request_diff, on: :create, unless: [:allow_broken, :importing?] scope :by_branch, ->(branch_name) { where("(source_branch LIKE :branch) OR (target_branch LIKE :branch)", branch: branch_name) } scope :cared, ->(user) { where('assignee_id = :user OR author_id = :user', user: user.id) } @@ -286,6 +287,10 @@ class MergeRequest < ActiveRecord::Base end end + def ensure_merge_request_diff + merge_request_diff || merge_request_diffs.build + end + def create_merge_request_diff merge_request_diffs.create end diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 1e529c84706..da1e317027d 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -22,28 +22,31 @@ class MergeRequestDiff < ActiveRecord::Base serialize :st_commits serialize :st_diffs - validates :head_commit_sha, presence: true validates :start_commit_sha, presence: true + validates :head_commit_sha, presence: true validates :base_commit_sha, presence: true - after_initialize :ensure_head_commit_sha, if: :persisted? - before_create :set_diff_range, unless: :importing? - after_create :reload_content, unless: :importing? - after_save :keep_around_commits, unless: :importing? - - def ensure_head_commit_sha - self.head_commit_sha ||= last_commit.sha - end + after_initialize :set_diff_range, unless: :importing? + after_create :save_git_content, unless: :importing? + after_save :keep_around_commits, unless: :importing? def set_diff_range - self.start_commit_sha ||= merge_request.target_branch_sha - self.head_commit_sha ||= merge_request.source_branch_sha - self.base_commit_sha ||= find_base_sha + if persisted? + # Workaround for old MergeRequestDiff object + # that does not have head_commit_sha in the database + self.head_commit_sha ||= last_commit.sha + else + self.start_commit_sha ||= merge_request.target_branch_sha + self.head_commit_sha ||= merge_request.source_branch_sha + self.base_commit_sha ||= find_base_sha + end end - def reload_content - reload_commits - reload_diffs + # Collect information about commits and diff from repository + # and save it to the database as serialized data + def save_git_content + save_commits + save_diffs end def size @@ -130,9 +133,9 @@ class MergeRequestDiff < ActiveRecord::Base array.map { |hash| Commit.new(Gitlab::Git::Commit.new(hash), merge_request.source_project) } end - # Reload all commits related to current merge request from repo + # Load all commits related to current merge request diff from repo # and save it as array of hashes in st_commits db field - def reload_commits + def save_commits new_attributes = {} commits = compare.commits @@ -165,9 +168,9 @@ class MergeRequestDiff < ActiveRecord::Base end end - # Reload diffs between branches related to current merge request from repo + # Load diffs between branches related to current merge request diff from repo # and save it as array of hashes in st_diffs db field - def reload_diffs + def save_diffs new_attributes = {} new_diffs = [] -- cgit v1.2.1 From 5cad2d290219d29aa2be6e991b42b73ac9d87754 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Jul 2016 17:26:54 +0300 Subject: Add improvements to merge request versions * show commits count in the merge request version dropdown * initialize base/start commit sha for old merge request diffs from repo Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 4 +++- app/views/projects/merge_requests/show/_versions.html.haml | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index da1e317027d..2bc0b2636f4 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -34,7 +34,9 @@ class MergeRequestDiff < ActiveRecord::Base if persisted? # Workaround for old MergeRequestDiff object # that does not have head_commit_sha in the database - self.head_commit_sha ||= last_commit.sha + self.start_commit_sha ||= merge_request.target_branch_sha + self.head_commit_sha ||= last_commit.sha + self.base_commit_sha ||= find_base_sha else self.start_commit_sha ||= merge_request.target_branch_sha self.head_commit_sha ||= merge_request.source_branch_sha diff --git a/app/views/projects/merge_requests/show/_versions.html.haml b/app/views/projects/merge_requests/show/_versions.html.haml index 8b7d866941c..93a06154022 100644 --- a/app/views/projects/merge_requests/show/_versions.html.haml +++ b/app/views/projects/merge_requests/show/_versions.html.haml @@ -20,8 +20,9 @@ #{merge_request_diff.head_commit.short_id} %br %small + #{number_with_delimiter(merge_request_diff.commits.count)} #{'commit'.pluralize(merge_request_diff.commits.count)}, = time_ago_with_tooltip(merge_request_diff.created_at) .pull-right %span.monospace - git diff #{@merge_request_diff.base_commit.short_id}..#{@merge_request_diff.head_commit.short_id} + #{@merge_request_diff.base_commit.short_id}..#{@merge_request_diff.head_commit.short_id} -- cgit v1.2.1 From 8e031ce3b29b186858ddda2a28a6ea8f98b2f749 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Jul 2016 17:41:35 +0300 Subject: Remove requirement for base_commit_sha to allow creation of merge requests for orphaned branches Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 2bc0b2636f4..da0c15ddeea 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -22,9 +22,8 @@ class MergeRequestDiff < ActiveRecord::Base serialize :st_commits serialize :st_diffs - validates :start_commit_sha, presence: true - validates :head_commit_sha, presence: true - validates :base_commit_sha, presence: true + validates :start_commit_sha, presence: true, unless: :importing? + validates :head_commit_sha, presence: true, unless: :importing? after_initialize :set_diff_range, unless: :importing? after_create :save_git_content, unless: :importing? -- cgit v1.2.1 From b0a023842d4e9fc29db7fa6c7168528d9e4ac09d Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Jul 2016 18:41:57 +0300 Subject: Reload merge request association reload when update code Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 618829891a0..08523e45c65 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -246,13 +246,7 @@ class MergeRequest < ActiveRecord::Base end def diff_refs - return unless diff_start_commit || diff_base_commit - - Gitlab::Diff::DiffRefs.new( - base_sha: diff_base_sha, - start_sha: diff_start_sha, - head_sha: diff_head_sha - ) + merge_request_diff.diff_refs end def validate_branches @@ -306,6 +300,7 @@ class MergeRequest < ActiveRecord::Base old_diff_refs = self.diff_refs create_merge_request_diff + merge_request_diffs.reload new_diff_refs = self.diff_refs update_diff_notes_positions( -- cgit v1.2.1 From 0e974b52d8f5806c24fdc80ef5b62b261f5be2ba Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Jul 2016 22:36:18 +0300 Subject: Refactor MergeRequestDiff initialize method Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'app') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index da0c15ddeea..940a1016302 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -25,22 +25,18 @@ class MergeRequestDiff < ActiveRecord::Base validates :start_commit_sha, presence: true, unless: :importing? validates :head_commit_sha, presence: true, unless: :importing? - after_initialize :set_diff_range, unless: :importing? - after_create :save_git_content, unless: :importing? - after_save :keep_around_commits, unless: :importing? - - def set_diff_range - if persisted? - # Workaround for old MergeRequestDiff object - # that does not have head_commit_sha in the database - self.start_commit_sha ||= merge_request.target_branch_sha - self.head_commit_sha ||= last_commit.sha - self.base_commit_sha ||= find_base_sha - else - self.start_commit_sha ||= merge_request.target_branch_sha - self.head_commit_sha ||= merge_request.source_branch_sha - self.base_commit_sha ||= find_base_sha - end + after_initialize :initialize_commits_sha, unless: :importing? + after_create :save_git_content, unless: :importing? + after_save :keep_around_commits, unless: :importing? + + # Those variables are used for collecting commits and diff from git repository. + # After object is created those sha are stored in the database. + # However some old MergeRequestDiff records don't + # have those variables in the database so we try to initialize it + def initialize_commits_sha + self.start_commit_sha ||= merge_request.target_branch_sha + self.head_commit_sha ||= last_commit.try(:sha) || merge_request.source_branch_sha + self.base_commit_sha ||= find_base_sha end # Collect information about commits and diff from repository -- cgit v1.2.1 From 3c1dca0301366c63d1800aa11e73a82e68e120d0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 28 Jul 2016 23:40:13 +0300 Subject: Add more tests to merge_request_diff and improve initialize Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 4 +++- app/models/merge_request_diff.rb | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 08523e45c65..6d36a5ba288 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -246,7 +246,9 @@ class MergeRequest < ActiveRecord::Base end def diff_refs - merge_request_diff.diff_refs + if merge_request_diff + merge_request_diff.diff_refs + end end def validate_branches diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 940a1016302..b668b62cdac 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -35,7 +35,7 @@ class MergeRequestDiff < ActiveRecord::Base # have those variables in the database so we try to initialize it def initialize_commits_sha self.start_commit_sha ||= merge_request.target_branch_sha - self.head_commit_sha ||= last_commit.try(:sha) || merge_request.source_branch_sha + self.head_commit_sha ||= persisted? ? last_commit.sha : merge_request.source_branch_sha self.base_commit_sha ||= find_base_sha end @@ -191,9 +191,7 @@ class MergeRequestDiff < ActiveRecord::Base end new_attributes[:st_diffs] = new_diffs - update_columns_serialized(new_attributes) - keep_around_commits end -- cgit v1.2.1 From f8aeb8cdac98108bca5d1be2a382c32df6a500e5 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 1 Aug 2016 18:41:21 +0300 Subject: Change merge request diff creation from callback to part of the service Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/merge_requests_controller.rb | 1 - app/models/merge_request.rb | 5 ----- app/services/merge_requests/create_service.rb | 1 + 3 files changed, 1 insertion(+), 6 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index a886af713d5..33188e88385 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -88,7 +88,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController @merge_request.merge_request_diff end - respond_to do |format| format.html { define_discussion_vars } format.json { render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } } diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 6d36a5ba288..85048f928dc 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -15,7 +15,6 @@ class MergeRequest < ActiveRecord::Base serialize :merge_params, Hash - before_validation :ensure_merge_request_diff, on: :create, unless: :importing? after_update :update_merge_request_diff delegate :commits, :real_size, to: :merge_request_diff, prefix: nil @@ -283,10 +282,6 @@ class MergeRequest < ActiveRecord::Base end end - def ensure_merge_request_diff - merge_request_diff || merge_request_diffs.build - end - def create_merge_request_diff merge_request_diffs.create end diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index 96a25330af1..553d7443c86 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -16,6 +16,7 @@ module MergeRequests merge_request.target_project ||= source_project merge_request.author = current_user merge_request.merge_params['force_remove_source_branch'] = force_remove_source_branch + merge_request.merge_request_diffs.build if merge_request.save merge_request.update_attributes(label_ids: label_params) -- cgit v1.2.1 From 6515ec09bbfa25027d1b8a1240e09bc1c6edbcfb Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 2 Aug 2016 15:38:03 +0300 Subject: Chnage the way how merge request diff is initialized and saved Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 15 +++----- app/models/merge_request_diff.rb | 54 +++++++++++++++------------ app/services/merge_requests/create_service.rb | 1 - 3 files changed, 37 insertions(+), 33 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 85048f928dc..6f2216ab5db 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -11,11 +11,13 @@ class MergeRequest < ActiveRecord::Base belongs_to :merge_user, class_name: "User" has_many :merge_request_diffs, dependent: :destroy + has_one :merge_request_diff has_many :events, as: :target, dependent: :destroy serialize :merge_params, Hash - after_update :update_merge_request_diff + after_create :ensure_merge_request_diff, unless: :importing? + after_update :reload_diff_if_branch_changed delegate :commits, :real_size, to: :merge_request_diff, prefix: nil @@ -94,7 +96,6 @@ class MergeRequest < ActiveRecord::Base validates :merge_user, presence: true, if: :merge_when_build_succeeds? validate :validate_branches, unless: [:allow_broken, :importing?] validate :validate_fork - validates_associated :merge_request_diff, on: :create, unless: [:allow_broken, :importing?] scope :by_branch, ->(branch_name) { where("(source_branch LIKE :branch) OR (target_branch LIKE :branch)", branch: branch_name) } scope :cared, ->(user) { where('assignee_id = :user OR author_id = :user', user: user.id) } @@ -282,11 +283,11 @@ class MergeRequest < ActiveRecord::Base end end - def create_merge_request_diff - merge_request_diffs.create + def ensure_merge_request_diff + merge_request_diff || create_merge_request_diff end - def update_merge_request_diff + def reload_diff_if_branch_changed if source_branch_changed? || target_branch_changed? reload_diff end @@ -689,8 +690,4 @@ class MergeRequest < ActiveRecord::Base def keep_around_commit project.repository.keep_around(self.merge_commit_sha) end - - def merge_request_diff - merge_request_diffs.first - end end diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index b668b62cdac..074d8f5d40a 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -22,28 +22,28 @@ class MergeRequestDiff < ActiveRecord::Base serialize :st_commits serialize :st_diffs - validates :start_commit_sha, presence: true, unless: :importing? - validates :head_commit_sha, presence: true, unless: :importing? + # For compatibility with old MergeRequestDiff which + # does not store those variables in database + after_initialize :ensure_commits_sha, if: :persisted? - after_initialize :initialize_commits_sha, unless: :importing? + # All diff information is collected from repository after object is created. + # It allows you to override variables like head_commit_sha before getting diff. after_create :save_git_content, unless: :importing? - after_save :keep_around_commits, unless: :importing? - - # Those variables are used for collecting commits and diff from git repository. - # After object is created those sha are stored in the database. - # However some old MergeRequestDiff records don't - # have those variables in the database so we try to initialize it - def initialize_commits_sha - self.start_commit_sha ||= merge_request.target_branch_sha - self.head_commit_sha ||= persisted? ? last_commit.sha : merge_request.source_branch_sha - self.base_commit_sha ||= find_base_sha - end # Collect information about commits and diff from repository # and save it to the database as serialized data def save_git_content + ensure_commits_sha save_commits + reload_commits save_diffs + keep_around_commits + end + + def ensure_commits_sha + self.start_commit_sha ||= merge_request.target_branch_sha + self.head_commit_sha ||= last_commit.try(:sha) || merge_request.source_branch_sha + self.base_commit_sha ||= find_base_sha end def size @@ -52,14 +52,15 @@ class MergeRequestDiff < ActiveRecord::Base def diffs(options={}) if options[:ignore_whitespace_change] - @diffs_no_whitespace ||= begin - compare = Gitlab::Git::Compare.new( - repository.raw_repository, - start_commit_sha, - head_commit_sha - ) - compare.diffs(options) - end + @diffs_no_whitespace ||= + begin + compare = Gitlab::Git::Compare.new( + repository.raw_repository, + start_commit_sha, + head_commit_sha + ) + compare.diffs(options) + end else @diffs ||= {} @diffs[options] ||= load_diffs(st_diffs, options) @@ -70,6 +71,11 @@ class MergeRequestDiff < ActiveRecord::Base @commits ||= load_commits(st_commits || []) end + def reload_commits + @commits = nil + commits + end + def last_commit commits.first end @@ -192,7 +198,6 @@ class MergeRequestDiff < ActiveRecord::Base new_attributes[:st_diffs] = new_diffs update_columns_serialized(new_attributes) - keep_around_commits end def project @@ -207,6 +212,9 @@ class MergeRequestDiff < ActiveRecord::Base return unless head_commit_sha && start_commit_sha project.merge_base_commit(head_commit_sha, start_commit_sha).try(:sha) + rescue Rugged::OdbError + # In case head or start commit does not exist in the repository any more + nil end def utf8_st_diffs diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb index 553d7443c86..96a25330af1 100644 --- a/app/services/merge_requests/create_service.rb +++ b/app/services/merge_requests/create_service.rb @@ -16,7 +16,6 @@ module MergeRequests merge_request.target_project ||= source_project merge_request.author = current_user merge_request.merge_params['force_remove_source_branch'] = force_remove_source_branch - merge_request.merge_request_diffs.build if merge_request.save merge_request.update_attributes(label_ids: label_params) -- cgit v1.2.1 From 7cb8ceb5b9b7da6f9bd5f80a50eeca6727ac5902 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 2 Aug 2016 16:28:37 +0300 Subject: Fix creation and reload of the merge request diff Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 6f2216ab5db..8b0b413343c 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -11,7 +11,9 @@ class MergeRequest < ActiveRecord::Base belongs_to :merge_user, class_name: "User" has_many :merge_request_diffs, dependent: :destroy - has_one :merge_request_diff + has_one :merge_request_diff, + -> { order('merge_request_diffs.id DESC') } + has_many :events, as: :target, dependent: :destroy serialize :merge_params, Hash @@ -287,6 +289,15 @@ class MergeRequest < ActiveRecord::Base merge_request_diff || create_merge_request_diff end + def create_merge_request_diff + merge_request_diffs.create + reload_merge_request_diff + end + + def reload_merge_request_diff + merge_request_diff(true) + end + def reload_diff_if_branch_changed if source_branch_changed? || target_branch_changed? reload_diff @@ -298,7 +309,6 @@ class MergeRequest < ActiveRecord::Base old_diff_refs = self.diff_refs create_merge_request_diff - merge_request_diffs.reload new_diff_refs = self.diff_refs update_diff_notes_positions( -- cgit v1.2.1 From fc8d2fbc946d144d2a9d075d67a9f1fe1035da0e Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 2 Aug 2016 17:52:20 +0300 Subject: Build diff_refs for merge request if merge request diff does not exist Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 8b0b413343c..56d5157298f 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -250,6 +250,12 @@ class MergeRequest < ActiveRecord::Base def diff_refs if merge_request_diff merge_request_diff.diff_refs + elsif diff_start_commit || diff_base_commit + Gitlab::Diff::DiffRefs.new( + base_sha: diff_base_sha, + start_sha: diff_start_sha, + head_sha: diff_head_sha + ) end end -- cgit v1.2.1 From d99d5198c2df6f931664b8096bcbfc28e8221145 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 8 Aug 2016 23:00:11 +0300 Subject: Add MergeRequest#branch_merge_base_commit method Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 56d5157298f..7e3444882ea 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -177,8 +177,8 @@ class MergeRequest < ActiveRecord::Base def diff_base_commit if persisted? merge_request_diff.base_commit - elsif diff_start_commit && diff_head_commit - self.target_project.merge_base_commit(diff_start_sha, diff_head_sha) + else + branch_merge_base_commit end end @@ -239,6 +239,15 @@ class MergeRequest < ActiveRecord::Base target_project.repository.commit(target_branch) if target_branch_ref end + def branch_merge_base_commit + start_sha = target_branch_sha + head_sha = source_branch_sha + + if start_sha && head_sha + target_project.merge_base_commit(start_sha, head_sha) + end + end + def target_branch_sha @target_branch_sha || target_branch_head.try(:sha) end @@ -247,15 +256,25 @@ class MergeRequest < ActiveRecord::Base @source_branch_sha || source_branch_head.try(:sha) end + def branch_merge_base_sha + branch_merge_base_commit.try(:sha) + end + def diff_refs if merge_request_diff merge_request_diff.diff_refs - elsif diff_start_commit || diff_base_commit - Gitlab::Diff::DiffRefs.new( - base_sha: diff_base_sha, - start_sha: diff_start_sha, - head_sha: diff_head_sha - ) + else + start_sha = target_branch_sha + head_sha = source_branch_sha + base_sha = branch_merge_base_sha + + if start_sha || base_sha + Gitlab::Diff::DiffRefs.new( + base_sha: base_sha, + start_sha: start_sha, + head_sha: head_sha + ) + end end end -- cgit v1.2.1 From 28e33df46bdffac3dc9388b56035db38dcdab5e3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Tue, 9 Aug 2016 15:16:50 +0300 Subject: Load merge request versions without loading whole diff from database Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 4 ++++ app/views/projects/merge_requests/show/_versions.html.haml | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 074d8f5d40a..24e09c4d57c 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -30,6 +30,10 @@ class MergeRequestDiff < ActiveRecord::Base # It allows you to override variables like head_commit_sha before getting diff. after_create :save_git_content, unless: :importing? + def self.select_without_diff + select(column_names - ['st_diffs']) + end + # Collect information about commits and diff from repository # and save it to the database as serialized data def save_git_content diff --git a/app/views/projects/merge_requests/show/_versions.html.haml b/app/views/projects/merge_requests/show/_versions.html.haml index 93a06154022..84c2b83e330 100644 --- a/app/views/projects/merge_requests/show/_versions.html.haml +++ b/app/views/projects/merge_requests/show/_versions.html.haml @@ -1,7 +1,7 @@ -- diffs_count = @merge_request.merge_request_diffs.count +- merge_request_diffs = @merge_request.merge_request_diffs.select_without_diff +- latest_diff = merge_request_diffs.first -- if diffs_count > 1 - - latest_diff = @merge_request.merge_request_diff +- if merge_request_diffs.size > 1 .mr-version-switch Version:  %span.dropdown.inline @@ -13,7 +13,7 @@ #{@merge_request_diff.head_commit.short_id} %span.caret %ul.dropdown-menu.dropdown-menu-selectable - - @merge_request.merge_request_diffs.each do |merge_request_diff| + - merge_request_diffs.each do |merge_request_diff| %li = link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request, diff_id: merge_request_diff.id), class: ('is-active' if merge_request_diff == @merge_request_diff) do %strong.monospace -- cgit v1.2.1 From 3eae0641ef0708f9b223abbe0070e332ea0b20ac Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 10 Aug 2016 18:40:10 +0800 Subject: Introduce Pipeline#latest and Pipeline.latest_for: So that we could easily access it for the view --- app/models/ci/pipeline.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index bce6a992af6..bc1190537da 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -21,8 +21,12 @@ module Ci after_save :keep_around_commits # ref can't be HEAD or SHA, can only be branch/tag name - scope :latest_successful_for, ->(ref = default_branch) do - where(ref: ref).success.order(id: :desc).limit(1) + scope :latest_successful_for, ->(ref) do + latest(ref).success + end + + scope :latest_for, ->(ref) do + where(ref: ref).order(id: :desc).limit(1) end def self.truncate_sha(sha) @@ -98,6 +102,10 @@ module Ci end end + def latest + project.pipelines.latest_for(ref).first + end + def latest? return false unless ref commit = project.commit(ref) -- cgit v1.2.1 From 517249858e41694f51b67461b313d5a34c2a466c Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 10 Aug 2016 21:07:26 +0800 Subject: It's latest_for, not just latest --- app/models/ci/pipeline.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index bc1190537da..50f9ee7fc66 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -22,7 +22,7 @@ module Ci # ref can't be HEAD or SHA, can only be branch/tag name scope :latest_successful_for, ->(ref) do - latest(ref).success + latest_for(ref).success end scope :latest_for, ->(ref) do -- cgit v1.2.1 From 4b559c9afb34b80b910efec514653c6ea65adba8 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 11 Aug 2016 17:26:04 +0800 Subject: Reverse ref and sha in args and rename pipeline to pipeline_for --- app/models/merge_request.rb | 3 ++- app/models/project.rb | 7 ++++--- app/views/projects/issues/_related_branches.html.haml | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b1fb3ce5d69..7c8e938df75 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -666,7 +666,8 @@ class MergeRequest < ActiveRecord::Base end def pipeline - @pipeline ||= source_project.pipeline(diff_head_sha, source_branch) if diff_head_sha && source_project + return unless diff_head_sha && source_project + @pipeline ||= source_project.pipeline_for(source_branch, diff_head_sha) end def merge_commit diff --git a/app/models/project.rb b/app/models/project.rb index d306f86f783..dc9b4b38a10 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1086,12 +1086,13 @@ class Project < ActiveRecord::Base !namespace.share_with_group_lock end - def pipeline(sha, ref) + def pipeline_for(ref, sha) pipelines.order(id: :desc).find_by(sha: sha, ref: ref) end - def ensure_pipeline(sha, ref, current_user = nil) - pipeline(sha, ref) || pipelines.create(sha: sha, ref: ref, user: current_user) + def ensure_pipeline(ref, sha, current_user = nil) + pipeline_for(ref, sha) || + pipelines.create(sha: sha, ref: ref, user: current_user) end def enable_ci diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml index 6ea9f612d13..a8eeab3e55e 100644 --- a/app/views/projects/issues/_related_branches.html.haml +++ b/app/views/projects/issues/_related_branches.html.haml @@ -5,7 +5,7 @@ - @related_branches.each do |branch| %li - target = @project.repository.find_branch(branch).target - - pipeline = @project.pipeline(target.sha, branch) if target + - pipeline = @project.pipeline_for(branch, target.sha) if target - if pipeline %span.related-branch-ci-status = render_pipeline_status(pipeline) -- cgit v1.2.1 From 0a9d9f7d5096aa742564e704a96fa7c40eeaf007 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 11 Aug 2016 17:55:23 +0800 Subject: Fetch the current SHA if SHA was not passed --- app/models/project.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index dc9b4b38a10..2969bec0bf7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1086,7 +1086,8 @@ class Project < ActiveRecord::Base !namespace.share_with_group_lock end - def pipeline_for(ref, sha) + def pipeline_for(ref, sha = commit(ref).try(:sha)) + return unless sha pipelines.order(id: :desc).find_by(sha: sha, ref: ref) end -- cgit v1.2.1 From 2a435e1d116065496fcb82f9b2182f7037d4c8b3 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 11 Aug 2016 18:04:52 +0800 Subject: Remove Pipeline#latest in favour of Project#pipeline_for(ref) --- app/models/ci/pipeline.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 50f9ee7fc66..9621bddf8dc 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -102,10 +102,6 @@ module Ci end end - def latest - project.pipelines.latest_for(ref).first - end - def latest? return false unless ref commit = project.commit(ref) -- cgit v1.2.1 From d84aa560331a646016880e4d2c5c0a3b3d4b32a6 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 11 Aug 2016 18:09:26 +0800 Subject: Make Pipeline.latest_successful_for return the record --- app/models/ci/pipeline.rb | 8 ++------ app/models/project.rb | 2 +- app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/buttons/_download.html.haml | 2 +- app/views/projects/repositories/_download_archive.html.haml | 2 +- app/views/projects/tags/_download.html.haml | 2 +- 6 files changed, 7 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 9621bddf8dc..0289a51eedd 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -21,12 +21,8 @@ module Ci after_save :keep_around_commits # ref can't be HEAD or SHA, can only be branch/tag name - scope :latest_successful_for, ->(ref) do - latest_for(ref).success - end - - scope :latest_for, ->(ref) do - where(ref: ref).order(id: :desc).limit(1) + def self.latest_successful_for(ref) + where(ref: ref).order(id: :desc).success.first end def self.truncate_sha(sha) diff --git a/app/models/project.rb b/app/models/project.rb index 2969bec0bf7..7aa34cdeec8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -432,7 +432,7 @@ class Project < ActiveRecord::Base # ref can't be HEAD, can only be branch/tag name or SHA def latest_successful_builds_for(ref = default_branch) - latest_pipeline = pipelines.latest_successful_for(ref).first + latest_pipeline = pipelines.latest_successful_for(ref) if latest_pipeline latest_pipeline.builds.latest.with_artifacts diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index b096516c627..2029758f30d 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -27,7 +27,7 @@ = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-default', method: :post, title: "Compare" do Compare - - pipeline = @project.pipelines.latest_successful_for(branch.name).first + - pipeline = @project.pipelines.latest_successful_for(branch.name) - if pipeline - artifacts = pipeline.builds.latest.with_artifacts - if artifacts.any? diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index d135b448dd7..e7ef0cbaa91 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -14,7 +14,7 @@ %li = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - pipeline = @project.pipelines.latest_successful_for(@ref).first + - pipeline = @project.pipelines.latest_successful_for(@ref) - if pipeline - artifacts = pipeline.builds.latest.with_artifacts - if artifacts.any? diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index 183daebfc3a..0ef9ad5f789 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -25,7 +25,7 @@ = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar'), rel: 'nofollow' do %i.fa.fa-download %span Download tar - - pipeline = @project.pipelines.latest_successful_for(ref).first + - pipeline = @project.pipelines.latest_successful_for(ref) - if pipeline - artifacts = pipeline.builds.latest.with_artifacts - if artifacts.any? diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index bb2e5224306..ba3fd4627af 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -12,7 +12,7 @@ %li = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - pipeline = project.pipelines.latest_successful_for(ref).first + - pipeline = project.pipelines.latest_successful_for(ref) - if pipeline - artifacts = pipeline.builds.latest.with_artifacts - if artifacts.any? -- cgit v1.2.1 From 62d991c80f0b5716945912ebf2031f56da75a12b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 11 Aug 2016 19:04:45 +0800 Subject: Show latest pipeline status if what provided artifacts aren't latest --- app/views/projects/branches/_branch.html.haml | 5 ++++- app/views/projects/buttons/_download.html.haml | 5 ++++- app/views/projects/repositories/_download_archive.html.haml | 5 ++++- app/views/projects/tags/_download.html.haml | 5 ++++- 4 files changed, 16 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 2029758f30d..8a33cd1502c 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -40,7 +40,10 @@ %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_pipeline_path(@project.namespace, @project, pipeline))})" + - latest_pipeline = @project.pipeline_for(branch.name) + %li + %span= latest_pipeline.status.humanize + %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(@project.namespace, @project, branch.name, 'download', job: job.name), rel: 'nofollow' do diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index e7ef0cbaa91..84135a6d049 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -20,7 +20,10 @@ - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_pipeline_path(@project.namespace, @project, pipeline))})" + - latest_pipeline = @project.pipeline_for(@ref) + %li + %span= latest_pipeline.status.humanize + %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(@project.namespace, @project, @ref, 'download', job: job.name), rel: 'nofollow' do diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index 0ef9ad5f789..c9a0b74e47b 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -31,7 +31,10 @@ - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_pipeline_path(@project.namespace, @project, pipeline))})" + - latest_pipeline = @project.pipeline_for(ref) + %li + %span= latest_pipeline.status.humanize + %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(@project.namespace, @project, ref, 'download', job: job.name), rel: 'nofollow' do diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index ba3fd4627af..10e8f77ac0c 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -18,7 +18,10 @@ - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? - = " (not latest, but #{link_to(pipeline.short_sha, namespace_project_pipeline_path(project.namespace, project, pipeline))})" + - latest_pipeline = @project.pipeline_for(ref) + %li + %span= latest_pipeline.status.humanize + %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li = link_to search_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do -- cgit v1.2.1 From 445edcfacc583ba613a4b865b104d7d7e1f7ec0f Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 12 Aug 2016 13:08:16 +0300 Subject: Remove unnecessary   in merge request versions dropdown Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/merge_requests/show/_versions.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/merge_requests/show/_versions.html.haml b/app/views/projects/merge_requests/show/_versions.html.haml index 84c2b83e330..15d94b16ced 100644 --- a/app/views/projects/merge_requests/show/_versions.html.haml +++ b/app/views/projects/merge_requests/show/_versions.html.haml @@ -3,7 +3,7 @@ - if merge_request_diffs.size > 1 .mr-version-switch - Version:  + Version: %span.dropdown.inline %a.btn-link.dropdown-toggle{ data: {toggle: :dropdown} } %strong.monospace< -- cgit v1.2.1 From 29ac60d7fbb8208880408dbf98a94acd0ae73730 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 15 Aug 2016 15:20:36 +0300 Subject: Change the way old merge request diff handled Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request.rb | 2 +- app/models/merge_request_diff.rb | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 7e3444882ea..b7c2afb0920 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -261,7 +261,7 @@ class MergeRequest < ActiveRecord::Base end def diff_refs - if merge_request_diff + if persisted? merge_request_diff.diff_refs else start_sha = target_branch_sha diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 24e09c4d57c..4c18775c44a 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -22,10 +22,6 @@ class MergeRequestDiff < ActiveRecord::Base serialize :st_commits serialize :st_diffs - # For compatibility with old MergeRequestDiff which - # does not store those variables in database - after_initialize :ensure_commits_sha, if: :persisted? - # All diff information is collected from repository after object is created. # It allows you to override variables like head_commit_sha before getting diff. after_create :save_git_content, unless: :importing? @@ -50,6 +46,20 @@ class MergeRequestDiff < ActiveRecord::Base self.base_commit_sha ||= find_base_sha end + # This method will rely on repository branch sha + # in case start_commit_sha is nil. Its necesarry for old merge request diff + # created before version 8.4 to work + def safe_start_commit_sha + start_commit_sha || merge_request.target_branch_sha + end + + # This method will rely on repository branch sha + # in case head_commit_sha is nil. Its necesarry for old merge request diff + # created before version 8.4 to work + def safe_head_commit_sha + head_commit_sha || last_commit.try(:sha) || merge_request.source_branch_sha + end + def size real_size.presence || diffs.size end @@ -60,8 +70,8 @@ class MergeRequestDiff < ActiveRecord::Base begin compare = Gitlab::Git::Compare.new( repository.raw_repository, - start_commit_sha, - head_commit_sha + safe_start_commit_sha, + safe_head_commit_sha ) compare.diffs(options) end @@ -126,8 +136,8 @@ class MergeRequestDiff < ActiveRecord::Base Gitlab::Git::Compare.new( repository.raw_repository, - start_commit_sha, - head_commit_sha + safe_start_commit_sha, + safe_head_commit_sha ) end end @@ -216,9 +226,6 @@ class MergeRequestDiff < ActiveRecord::Base return unless head_commit_sha && start_commit_sha project.merge_base_commit(head_commit_sha, start_commit_sha).try(:sha) - rescue Rugged::OdbError - # In case head or start commit does not exist in the repository any more - nil end def utf8_st_diffs -- cgit v1.2.1 From 94a7198ade54595d72797cab09db2c2a89172535 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 15 Aug 2016 16:25:29 +0300 Subject: Fix merge request diff create and head_commit_sha compatibility Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 4c18775c44a..950b00f1001 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -42,8 +42,19 @@ class MergeRequestDiff < ActiveRecord::Base def ensure_commits_sha self.start_commit_sha ||= merge_request.target_branch_sha - self.head_commit_sha ||= last_commit.try(:sha) || merge_request.source_branch_sha + self.head_commit_sha ||= merge_request.source_branch_sha self.base_commit_sha ||= find_base_sha + save + end + + # Override head_commit_sha to keep compatibility with merge request diff + # created before version 8.4 that does not store head_commit_sha in separate db field. + def head_commit_sha + if persisted? && super.nil? + last_commit.try(:sha) + else + super + end end # This method will rely on repository branch sha @@ -57,7 +68,7 @@ class MergeRequestDiff < ActiveRecord::Base # in case head_commit_sha is nil. Its necesarry for old merge request diff # created before version 8.4 to work def safe_head_commit_sha - head_commit_sha || last_commit.try(:sha) || merge_request.source_branch_sha + head_commit_sha || merge_request.source_branch_sha end def size @@ -111,7 +122,7 @@ class MergeRequestDiff < ActiveRecord::Base end def head_commit - return last_commit unless head_commit_sha + return unless head_commit_sha project.commit(head_commit_sha) end -- cgit v1.2.1 From 643a368fa437725cbfffcfdc251055c4d125438c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 15 Aug 2016 17:57:19 +0300 Subject: Make merge request diff works with new FileCollection logic Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/merge_requests_controller.rb | 2 +- app/models/merge_request.rb | 6 +++--- app/models/merge_request_diff.rb | 14 +++++++++----- app/views/projects/merge_requests/show/_diffs.html.haml | 1 + 4 files changed, 14 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index a0b80c823fb..a4b1262896c 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -91,7 +91,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController respond_to do |format| format.html { define_discussion_vars } format.json do - @diffs = @merge_request.diffs(diff_options) + @diffs = @merge_request_diff.diffs(diff_options) render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 7c3845ef538..104f9c7223d 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -172,10 +172,10 @@ class MergeRequest < ActiveRecord::Base end def diffs(diff_options = nil) - if self.compare - self.compare.diffs(diff_options) + if compare + compare.diffs(diff_options) else - Gitlab::Diff::FileCollection::MergeRequest.new(self, diff_options: diff_options) + merge_request_diff.diffs(diff_options) end end diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 8920641cfec..9a34d099acd 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -141,7 +141,13 @@ class MergeRequestDiff < ActiveRecord::Base base_commit_sha? && head_commit_sha? && start_commit_sha? end - private + def diffs(diff_options = nil) + Gitlab::Diff::FileCollection::MergeRequestDiff.new(self, diff_options: diff_options) + end + + def project + merge_request.target_project + end def compare @compare ||= @@ -157,6 +163,8 @@ class MergeRequestDiff < ActiveRecord::Base end end + private + def dump_commits(commits) commits.map(&:to_hash) end @@ -229,10 +237,6 @@ class MergeRequestDiff < ActiveRecord::Base update_columns_serialized(new_attributes) end - def project - merge_request.target_project - end - def repository project.repository end diff --git a/app/views/projects/merge_requests/show/_diffs.html.haml b/app/views/projects/merge_requests/show/_diffs.html.haml index 013b05628fa..99c71e1454a 100644 --- a/app/views/projects/merge_requests/show/_diffs.html.haml +++ b/app/views/projects/merge_requests/show/_diffs.html.haml @@ -1,4 +1,5 @@ - if @merge_request_diff.collected? + = render 'projects/merge_requests/show/versions' = render "projects/diffs/diffs", diffs: @diffs - elsif @merge_request_diff.empty? .nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch} -- cgit v1.2.1 From 49d63dc131da899ac2c91c26fe7e22f02da34dbd Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 15 Aug 2016 18:11:18 +0300 Subject: Fix and refactor merge request diff_refs method Signed-off-by: Dmitriy Zaporozhets --- app/models/diff_note.rb | 6 +----- app/models/merge_request.rb | 17 ++--------------- app/models/merge_request_diff.rb | 2 +- 3 files changed, 4 insertions(+), 21 deletions(-) (limited to 'app') diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb index c816deb4e0c..364e1a8341b 100644 --- a/app/models/diff_note.rb +++ b/app/models/diff_note.rb @@ -79,11 +79,7 @@ class DiffNote < Note end def noteable_diff_refs - if noteable.respond_to?(:diff_sha_refs) - noteable.diff_sha_refs - else - noteable.diff_refs - end + noteable.diff_refs end def set_original_position diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 104f9c7223d..007c2aa74e1 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -270,7 +270,7 @@ class MergeRequest < ActiveRecord::Base end def diff_refs - if persisted? + if merge_request_diff && merge_request_diff.diff_refs_by_sha? merge_request_diff.diff_refs else start_sha = target_branch_sha @@ -287,19 +287,6 @@ class MergeRequest < ActiveRecord::Base end end - # Return diff_refs instance trying to not touch the git repository - def diff_sha_refs - if merge_request_diff && merge_request_diff.diff_refs_by_sha? - return Gitlab::Diff::DiffRefs.new( - base_sha: merge_request_diff.base_commit_sha, - start_sha: merge_request_diff.start_commit_sha, - head_sha: merge_request_diff.head_commit_sha - ) - else - diff_refs - end - end - def validate_branches if target_project == source_project && target_branch == source_branch errors.add :branch_conflict, "You can not use same project/branch for source and target" @@ -716,7 +703,7 @@ class MergeRequest < ActiveRecord::Base end def support_new_diff_notes? - diff_sha_refs && diff_sha_refs.complete? + diff_refs && diff_refs.complete? end def update_diff_notes_positions(old_diff_refs:, new_diff_refs:) diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 9a34d099acd..a769d31ac93 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -128,7 +128,7 @@ class MergeRequestDiff < ActiveRecord::Base end def diff_refs - return unless start_commit || base_commit + return unless start_commit_sha || base_commit_sha Gitlab::Diff::DiffRefs.new( base_sha: base_commit_sha, -- cgit v1.2.1 From 73bbaffbfcfb24942111726ae6e04170f1b61ccc Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 16 Aug 2016 01:03:08 +0800 Subject: Use URL helper, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13880889 --- app/controllers/projects/artifacts_controller.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 05112571225..b7c395a01a3 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -35,10 +35,14 @@ class Projects::ArtifactsController < Projects::ApplicationController end def search - if params[:path] - url = namespace_project_build_url(project.namespace, project, build) + path = params[:path] - redirect_to "#{url}/artifacts/#{params[:path]}" + if %w[download browse file].include?(path) + redirect_to send( + "#{path}_namespace_project_build_artifacts_url", + project.namespace, + project, + build) else render_404 end -- cgit v1.2.1 From 16b63664f9d73a2ab83feac6eadf959f530208c9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 16 Aug 2016 01:15:29 +0800 Subject: It's project, not @project --- app/views/projects/tags/_download.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 10e8f77ac0c..27e0cd7b1f9 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -18,7 +18,7 @@ - if artifacts.any? %li.dropdown-header Artifacts - unless pipeline.latest? - - latest_pipeline = @project.pipeline_for(ref) + - latest_pipeline = project.pipeline_for(ref) %li %span= latest_pipeline.status.humanize %li.dropdown-header Previous Artifacts -- cgit v1.2.1 From 1501b1abc4be78eaa4cb4c28969d9bc59bcf284c Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Mon, 15 Aug 2016 23:48:43 +0200 Subject: Fixed bug when a pipeline for latest SHA does not exist --- app/helpers/ci_status_helper.rb | 5 +++++ app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/buttons/_download.html.haml | 2 +- app/views/projects/repositories/_download_archive.html.haml | 2 +- app/views/projects/tags/_download.html.haml | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index ea2f5f9281a..0f7fcc0416c 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -25,6 +25,11 @@ module CiStatusHelper end end + def ci_status_for_statuseable(subject) + status = subject.try(:status) || 'not found' + status.humanize + end + def ci_icon_for_status(status) icon_name = case status diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 8a33cd1502c..402e37f4ec6 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -42,7 +42,7 @@ - unless pipeline.latest? - latest_pipeline = @project.pipeline_for(branch.name) %li - %span= latest_pipeline.status.humanize + %span= ci_status_for_statuseable(latest_pipeline) %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 84135a6d049..a86561ca90b 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -22,7 +22,7 @@ - unless pipeline.latest? - latest_pipeline = @project.pipeline_for(@ref) %li - %span= latest_pipeline.status.humanize + %span= ci_status_for_statuseable(latest_pipeline) %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index c9a0b74e47b..e482bb72df4 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -33,7 +33,7 @@ - unless pipeline.latest? - latest_pipeline = @project.pipeline_for(ref) %li - %span= latest_pipeline.status.humanize + %span= ci_status_for_statuseable(latest_pipeline) %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 27e0cd7b1f9..b3bf18cfa50 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -20,7 +20,7 @@ - unless pipeline.latest? - latest_pipeline = project.pipeline_for(ref) %li - %span= latest_pipeline.status.humanize + %span= ci_status_for_statuseable(latest_pipeline) %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li -- cgit v1.2.1 From ad320577595610ee1cb8f945cdfe6f739e9a0ebb Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Mon, 15 Aug 2016 19:07:42 -0500 Subject: Add unclickable state to running build artifacts --- app/assets/stylesheets/framework/dropdowns.scss | 6 ++++++ app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/buttons/_download.html.haml | 2 +- app/views/projects/repositories/_download_archive.html.haml | 2 +- app/views/projects/tags/_download.html.haml | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index e8eafa15899..cbbff49ad9c 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -176,6 +176,12 @@ .separator + .dropdown-header { padding-top: 2px; } + + .unclickable { + cursor: not-allowed; + padding: 5px 8px; + color: $dropdown-header-color; + } } .dropdown-menu-large { diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 402e37f4ec6..12b78be4be0 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -42,7 +42,7 @@ - unless pipeline.latest? - latest_pipeline = @project.pipeline_for(branch.name) %li - %span= ci_status_for_statuseable(latest_pipeline) + .unclickable= ci_status_for_statuseable(latest_pipeline) %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index a86561ca90b..45998343fda 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -22,7 +22,7 @@ - unless pipeline.latest? - latest_pipeline = @project.pipeline_for(@ref) %li - %span= ci_status_for_statuseable(latest_pipeline) + .unclickable= ci_status_for_statuseable(latest_pipeline) %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index e482bb72df4..48502498171 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -33,7 +33,7 @@ - unless pipeline.latest? - latest_pipeline = @project.pipeline_for(ref) %li - %span= ci_status_for_statuseable(latest_pipeline) + .unclickable= ci_status_for_statuseable(latest_pipeline) %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index b3bf18cfa50..60f1e2cd2ee 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -20,7 +20,7 @@ - unless pipeline.latest? - latest_pipeline = project.pipeline_for(ref) %li - %span= ci_status_for_statuseable(latest_pipeline) + .unclickable= ci_status_for_statuseable(latest_pipeline) %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li -- cgit v1.2.1 From 11f840bfa5b93fdd0687c9c4f2a5a2e7abbc17ac Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 16 Aug 2016 21:04:06 +0800 Subject: An empty line after guard, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13904931 --- app/models/merge_request.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index cb60b626e75..96fecf7712a 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -676,6 +676,7 @@ class MergeRequest < ActiveRecord::Base def pipeline return unless diff_head_sha && source_project + @pipeline ||= source_project.pipeline_for(source_branch, diff_head_sha) end -- cgit v1.2.1 From f86a507745695f3b073d6edb6029836ab115765a Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 16 Aug 2016 22:10:10 +0800 Subject: Rename to latest_succeeded, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13908017 --- app/controllers/projects/artifacts_controller.rb | 2 +- app/views/projects/branches/_branch.html.haml | 2 +- app/views/projects/buttons/_download.html.haml | 2 +- app/views/projects/tags/_download.html.haml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index b7c395a01a3..5cc6d643b64 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -34,7 +34,7 @@ class Projects::ArtifactsController < Projects::ApplicationController redirect_to namespace_project_build_path(project.namespace, project, build) end - def search + def latest_succeeded path = params[:path] if %w[download browse file].include?(path) diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 12b78be4be0..5634abf3641 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -46,7 +46,7 @@ %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li - = link_to search_namespace_project_artifacts_path(@project.namespace, @project, branch.name, 'download', job: job.name), rel: 'nofollow' do + = link_to latest_succeeded_namespace_project_artifacts_path(@project.namespace, @project, branch.name, 'download', job: job.name), rel: 'nofollow' do %span Download '#{job.name}' - if can_remove_branch?(@project, branch.name) diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 45998343fda..177946dcd42 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -26,5 +26,5 @@ %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li - = link_to search_namespace_project_artifacts_path(@project.namespace, @project, @ref, 'download', job: job.name), rel: 'nofollow' do + = link_to latest_succeeded_namespace_project_artifacts_path(@project.namespace, @project, @ref, 'download', job: job.name), rel: 'nofollow' do %span Download '#{job.name}' diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 60f1e2cd2ee..316d03dd12a 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -24,5 +24,5 @@ %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li - = link_to search_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do + = link_to latest_succeeded_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do %span Download '#{job.name}' -- cgit v1.2.1 From 1c88ed7a515141b7468b238a679e2ff5cf86e3f9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 16 Aug 2016 22:14:27 +0800 Subject: Not sure why missed this one --- app/views/projects/repositories/_download_archive.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index 48502498171..c0a5909d3a6 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -37,5 +37,5 @@ %li.dropdown-header Previous Artifacts - artifacts.each do |job| %li - = link_to search_namespace_project_artifacts_path(@project.namespace, @project, ref, 'download', job: job.name), rel: 'nofollow' do + = link_to latest_succeeded_namespace_project_artifacts_path(@project.namespace, @project, ref, 'download', job: job.name), rel: 'nofollow' do %span Download '#{job.name}' -- cgit v1.2.1 From ee33b3e6e84bb566e84062e70d45c6d84ace4ee7 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 17 Aug 2016 17:06:31 +0800 Subject: Use partials for downloading artifacts button --- app/views/projects/branches/_branch.html.haml | 30 +++++++--------------- app/views/projects/buttons/_artifacts.html.haml | 14 ++++++++++ app/views/projects/buttons/_download.html.haml | 15 +---------- .../repositories/_download_archive.html.haml | 15 +---------- app/views/projects/tags/_download.html.haml | 15 +---------- 5 files changed, 26 insertions(+), 63 deletions(-) create mode 100644 app/views/projects/buttons/_artifacts.html.haml (limited to 'app') diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 5634abf3641..21ac675ffe0 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -27,27 +27,15 @@ = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-default', method: :post, title: "Compare" do Compare - - pipeline = @project.pipelines.latest_successful_for(branch.name) - - if pipeline - - artifacts = pipeline.builds.latest.with_artifacts - - if artifacts.any? - .dropdown.inline.artifacts-btn - %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } - = icon('download') - %span.caret - %span.sr-only - Select Archive Format - %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } - %li.dropdown-header Artifacts - - unless pipeline.latest? - - latest_pipeline = @project.pipeline_for(branch.name) - %li - .unclickable= ci_status_for_statuseable(latest_pipeline) - %li.dropdown-header Previous Artifacts - - artifacts.each do |job| - %li - = link_to latest_succeeded_namespace_project_artifacts_path(@project.namespace, @project, branch.name, 'download', job: job.name), rel: 'nofollow' do - %span Download '#{job.name}' + - if @project.latest_successful_builds_for(branch.name).any? + .dropdown.inline.artifacts-btn + %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } + = icon('download') + %span.caret + %span.sr-only + Select Archive Format + %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } + = render 'projects/buttons/artifacts', project: @project, ref: branch.name - if can_remove_branch?(@project, branch.name) = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-remove remove-row has-tooltip', title: "Delete branch", method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?", container: 'body' }, remote: true do diff --git a/app/views/projects/buttons/_artifacts.html.haml b/app/views/projects/buttons/_artifacts.html.haml new file mode 100644 index 00000000000..a52677ebf0a --- /dev/null +++ b/app/views/projects/buttons/_artifacts.html.haml @@ -0,0 +1,14 @@ +- pipeline = project.pipelines.latest_successful_for(ref) +- if pipeline + - artifacts = pipeline.builds.latest.with_artifacts + - if artifacts.any? + %li.dropdown-header Artifacts + - unless pipeline.latest? + - latest_pipeline = project.pipeline_for(ref) + %li + .unclickable= ci_status_for_statuseable(latest_pipeline) + %li.dropdown-header Previous Artifacts + - artifacts.each do |job| + %li + = link_to latest_succeeded_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do + %span Download '#{job.name}' diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 177946dcd42..5e748c44b08 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -14,17 +14,4 @@ %li = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - pipeline = @project.pipelines.latest_successful_for(@ref) - - if pipeline - - artifacts = pipeline.builds.latest.with_artifacts - - if artifacts.any? - %li.dropdown-header Artifacts - - unless pipeline.latest? - - latest_pipeline = @project.pipeline_for(@ref) - %li - .unclickable= ci_status_for_statuseable(latest_pipeline) - %li.dropdown-header Previous Artifacts - - artifacts.each do |job| - %li - = link_to latest_succeeded_namespace_project_artifacts_path(@project.namespace, @project, @ref, 'download', job: job.name), rel: 'nofollow' do - %span Download '#{job.name}' + = render 'projects/buttons/artifacts', project: @project, ref: @ref diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml index c0a5909d3a6..4f40696a190 100644 --- a/app/views/projects/repositories/_download_archive.html.haml +++ b/app/views/projects/repositories/_download_archive.html.haml @@ -25,17 +25,4 @@ = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar'), rel: 'nofollow' do %i.fa.fa-download %span Download tar - - pipeline = @project.pipelines.latest_successful_for(ref) - - if pipeline - - artifacts = pipeline.builds.latest.with_artifacts - - if artifacts.any? - %li.dropdown-header Artifacts - - unless pipeline.latest? - - latest_pipeline = @project.pipeline_for(ref) - %li - .unclickable= ci_status_for_statuseable(latest_pipeline) - %li.dropdown-header Previous Artifacts - - artifacts.each do |job| - %li - = link_to latest_succeeded_namespace_project_artifacts_path(@project.namespace, @project, ref, 'download', job: job.name), rel: 'nofollow' do - %span Download '#{job.name}' + = render 'projects/buttons/artifacts', project: @project, ref: ref diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml index 316d03dd12a..6985eb74ca7 100644 --- a/app/views/projects/tags/_download.html.haml +++ b/app/views/projects/tags/_download.html.haml @@ -12,17 +12,4 @@ %li = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do %span Download tar.gz - - pipeline = project.pipelines.latest_successful_for(ref) - - if pipeline - - artifacts = pipeline.builds.latest.with_artifacts - - if artifacts.any? - %li.dropdown-header Artifacts - - unless pipeline.latest? - - latest_pipeline = project.pipeline_for(ref) - %li - .unclickable= ci_status_for_statuseable(latest_pipeline) - %li.dropdown-header Previous Artifacts - - artifacts.each do |job| - %li - = link_to latest_succeeded_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do - %span Download '#{job.name}' + = render 'projects/buttons/artifacts', project: project, ref: ref -- cgit v1.2.1 From 4fbe044b74aa6a24133732ef8a9bc5063ecef5dd Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 17 Aug 2016 17:38:38 +0800 Subject: Use switch case in a helper, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_13988401 --- app/controllers/projects/artifacts_controller.rb | 10 +++------- app/helpers/gitlab_routing_helper.rb | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 5cc6d643b64..8261a73c642 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -35,14 +35,10 @@ class Projects::ArtifactsController < Projects::ApplicationController end def latest_succeeded - path = params[:path] + target_url = artifacts_action_url(params[:path], project, build) - if %w[download browse file].include?(path) - redirect_to send( - "#{path}_namespace_project_build_artifacts_url", - project.namespace, - project, - build) + if target_url + redirect_to(target_url) else render_404 end diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index 5386ddadc62..bc4d976ae68 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -149,4 +149,19 @@ module GitlabRoutingHelper def resend_invite_group_member_path(group_member, *args) resend_invite_group_group_member_path(group_member.source, group_member) end + + # Artifacts + + def artifacts_action_url(path, project, build) + args = [project.namespace, project, build] + + case path + when 'download' + download_namespace_project_build_artifacts_url(*args) + when 'browse' + browse_namespace_project_build_artifacts_url(*args) + when 'file' + file_namespace_project_build_artifacts_url(*args) + end + end end -- cgit v1.2.1 From e8b03baf6b67a14c0db6dbf3a1abaa4a6a173213 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 18 Aug 2016 15:31:20 +0800 Subject: Use path rather than URL because it should work for http 302: Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_14035941 --- app/controllers/projects/artifacts_controller.rb | 4 ++-- app/helpers/gitlab_routing_helper.rb | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 8261a73c642..16ab7ec409d 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -35,10 +35,10 @@ class Projects::ArtifactsController < Projects::ApplicationController end def latest_succeeded - target_url = artifacts_action_url(params[:path], project, build) + target_path = artifacts_action_path(params[:path], project, build) if target_url - redirect_to(target_url) + redirect_to(target_path) else render_404 end diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index bc4d976ae68..cd526f17b99 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -152,16 +152,16 @@ module GitlabRoutingHelper # Artifacts - def artifacts_action_url(path, project, build) + def artifacts_action_path(path, project, build) args = [project.namespace, project, build] case path when 'download' - download_namespace_project_build_artifacts_url(*args) + download_namespace_project_build_artifacts_path(*args) when 'browse' - browse_namespace_project_build_artifacts_url(*args) + browse_namespace_project_build_artifacts_path(*args) when 'file' - file_namespace_project_build_artifacts_url(*args) + file_namespace_project_build_artifacts_path(*args) end end end -- cgit v1.2.1 From 17d0406546885bedf2196c61a5991092b3fbe7c0 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 18 Aug 2016 19:30:20 +0800 Subject: Not sure why I missed this renaming --- app/controllers/projects/artifacts_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 16ab7ec409d..60e432d68d8 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -37,7 +37,7 @@ class Projects::ArtifactsController < Projects::ApplicationController def latest_succeeded target_path = artifacts_action_path(params[:path], project, build) - if target_url + if target_path redirect_to(target_path) else render_404 -- cgit v1.2.1 From b4398de5c5381a81f225c390e32f99d4e0e7d627 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Sun, 15 May 2016 00:50:15 +0100 Subject: Added new non-selectable selector exclusions to fix arrow key events, fixed the simulated clicking of a row and fixed the conflict between enter key form submit and enter key row selection Added bootstrap dropdown event triggers to invoke the open and close methods of the dropdown, allowing for the binding of array key events Added #17465 fix entry to CHANGELOG Fixed multi-dropdown selected row index conflict Fixed whitespace diff Added padding to the dropdown content iterative scroll as well as new conditional scrolls to scroll all the way to the top when the first item of a list is selected and to scroll all the way to the bottom when the last item of a list is selected Added conditionals to the enable and disable autocomplete methods to stop multiple invocations without any enabled/disabled state change Fixes some incorrect firing of requests. The dropdown box was invoking a new query every time it closed and the GitLabDropdownRemote callback was invoking a new query which was causing the dropdown double render issue. Added .selectable css class to dropdown list items that are not dividers or headers and altered selectors to account for that. Moved scroll padding Number to variable. Removed unused method Started Dropdown tests Added fixture and began first test Almost finished, navigation done, action and close needed YAY. TESTS DONE. Altered test and fixed click started removing selectable class use Fixed as reviewed altered selection method Fixed autocomplete shutting dropdown on arrow key use patched XSS vulns updated tests f Added click fixes --- app/assets/javascripts/gl_dropdown.js.coffee | 657 +++++++++++++++++++++ .../javascripts/search_autocomplete.js.coffee | 349 +++++++++++ 2 files changed, 1006 insertions(+) create mode 100644 app/assets/javascripts/gl_dropdown.js.coffee create mode 100644 app/assets/javascripts/search_autocomplete.js.coffee (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee new file mode 100644 index 00000000000..e096effaade --- /dev/null +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -0,0 +1,657 @@ +class GitLabDropdownFilter + BLUR_KEYCODES = [27, 40] + ARROW_KEY_CODES = [38, 40] + HAS_VALUE_CLASS = "has-value" + + constructor: (@input, @options) -> + { + @filterInputBlur = true + } = @options + + $inputContainer = @input.parent() + $clearButton = $inputContainer.find('.js-dropdown-input-clear') + + @indeterminateIds = [] + + # Clear click + $clearButton.on 'click', (e) => + e.preventDefault() + e.stopPropagation() + @input + .val('') + .trigger('keyup') + .focus() + + # Key events + timeout = "" + @input.on "keyup", (e) => + keyCode = e.which + + return if ARROW_KEY_CODES.indexOf(keyCode) >= 0 + + if @input.val() isnt "" and !$inputContainer.hasClass HAS_VALUE_CLASS + $inputContainer.addClass HAS_VALUE_CLASS + else if @input.val() is "" and $inputContainer.hasClass HAS_VALUE_CLASS + $inputContainer.removeClass HAS_VALUE_CLASS + + if keyCode is 13 + return false + + # Only filter asynchronously only if option remote is set + if @options.remote + clearTimeout timeout + timeout = setTimeout => + blur_field = @shouldBlur keyCode + + if blur_field and @filterInputBlur + @input.blur() + + @options.query @input.val(), (data) => + @options.callback(data) + , 250 + else + @filter @input.val() + + shouldBlur: (keyCode) -> + return BLUR_KEYCODES.indexOf(keyCode) >= 0 + + filter: (search_text) -> + @options.onFilter(search_text) if @options.onFilter + data = @options.data() + + if data? and not @options.filterByText + results = data + + if search_text isnt '' + # When data is an array of objects therefore [object Array] e.g. + # [ + # { prop: 'foo' }, + # { prop: 'baz' } + # ] + if _.isArray(data) + results = fuzzaldrinPlus.filter(data, search_text, + key: @options.keys + ) + else + # If data is grouped therefore an [object Object]. e.g. + # { + # groupName1: [ + # { prop: 'foo' }, + # { prop: 'baz' } + # ], + # groupName2: [ + # { prop: 'abc' }, + # { prop: 'def' } + # ] + # } + if gl.utils.isObject data + results = {} + for key, group of data + tmp = fuzzaldrinPlus.filter(group, search_text, + key: @options.keys + ) + + if tmp.length + results[key] = tmp.map (item) -> item + + @options.callback results + else + elements = @options.elements() + + if search_text + elements.each -> + $el = $(@) + matches = fuzzaldrinPlus.match($el.text().trim(), search_text) + + unless $el.is('.dropdown-header') + if matches.length + $el.show() + else + $el.hide() + else + elements.show() + +class GitLabDropdownRemote + constructor: (@dataEndpoint, @options) -> + + execute: -> + if typeof @dataEndpoint is "string" + @fetchData() + else if typeof @dataEndpoint is "function" + if @options.beforeSend + @options.beforeSend() + + # Fetch the data by calling the data funcfion + @dataEndpoint "", (data) => + if @options.success + @options.success(data) + + if @options.beforeSend + @options.beforeSend() + + # Fetch the data through ajax if the data is a string + fetchData: -> + $.ajax( + url: @dataEndpoint, + dataType: @options.dataType, + beforeSend: => + if @options.beforeSend + @options.beforeSend() + success: (data) => + if @options.success + @options.success(data) + ) + +class GitLabDropdown + LOADING_CLASS = "is-loading" + PAGE_TWO_CLASS = "is-page-two" + ACTIVE_CLASS = "is-active" + INDETERMINATE_CLASS = "is-indeterminate" + NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link' + SELECTABLE_CLASSES = ".dropdown-content li:not(#{NON_SELECTABLE_CLASSES})" + FILTER_INPUT = '.dropdown-input .dropdown-input-field' + currentIndex = -1 + CURSOR_SELECT_SCROLL_PADDING = 5 + + constructor: (@el, @options) -> + self = @ + selector = $(@el).data "target" + @dropdown = if selector? then $(selector) else $(@el).parent() + + # Set Defaults + { + # If no input is passed create a default one + @filterInput = @getElement(FILTER_INPUT) + @highlight = false + @filterInputBlur = true + } = @options + + self = @ + + # If selector was passed + if _.isString(@filterInput) + @filterInput = @getElement(@filterInput) + + searchFields = if @options.search then @options.search.fields else [] + + if @options.data + # If we provided data + # data could be an array of objects or a group of arrays + if _.isObject(@options.data) and not _.isFunction(@options.data) + @fullData = @options.data + @parseData @options.data + else + # Remote data + @remote = new GitLabDropdownRemote @options.data, { + dataType: @options.dataType, + beforeSend: @toggleLoading.bind(@) + success: (data) => + @fullData = data + + # Reset selected row index on new data + currentIndex = -1 + @parseData @fullData + + @filter.input.trigger('keyup') if @options.filterable and @filter and @filter.input + } + + # Init filterable + if @options.filterable + @filter = new GitLabDropdownFilter @filterInput, + filterInputBlur: @filterInputBlur + filterByText: @options.filterByText + onFilter: @options.onFilter + remote: @options.filterRemote + query: @options.data + keys: searchFields + elements: => + selector = SELECTABLE_CLASSES + + if @dropdown.find('.dropdown-toggle-page').length + selector = ".dropdown-page-one #{selector}" + + return $(selector) + data: => + return @fullData + callback: (data) => + @parseData data + + unless @filterInput.val() is '' + selector = '.dropdown-content li:not(.divider):visible' + + if @dropdown.find('.dropdown-toggle-page').length + selector = ".dropdown-page-one #{selector}" + + $(selector, @dropdown) + .first() + .find('a') + .addClass('is-focused') + + currentIndex = 0 + + + # Event listeners + + @dropdown.on "shown.bs.dropdown", @opened + @dropdown.on "hidden.bs.dropdown", @hidden + $(@el).on "update.label", @updateLabel + @dropdown.on "click", ".dropdown-menu, .dropdown-menu-close", @shouldPropagate + @dropdown.on 'keyup', (e) => + if e.which is 27 # Escape key + $('.dropdown-menu-close', @dropdown).trigger 'click' + @dropdown.on 'blur', 'a', (e) => + if e.relatedTarget? + $relatedTarget = $(e.relatedTarget) + $dropdownMenu = $relatedTarget.closest('.dropdown-menu') + + if $dropdownMenu.length is 0 + @dropdown.removeClass('open') + + if @dropdown.find(".dropdown-toggle-page").length + @dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on "click", (e) => + e.preventDefault() + e.stopPropagation() + + @togglePage() + + if @options.selectable + selector = ".dropdown-content a" + + if @dropdown.find(".dropdown-toggle-page").length + selector = ".dropdown-page-one .dropdown-content a" + + @dropdown.on "click", selector, (e) -> + $el = $(@) + selected = self.rowClicked $el + + if self.options.clicked + self.options.clicked(selected, $el, e) + + $el.trigger('blur') + + # Finds an element inside wrapper element + getElement: (selector) -> + @dropdown.find selector + + toggleLoading: -> + $('.dropdown-menu', @dropdown).toggleClass LOADING_CLASS + + togglePage: -> + menu = $('.dropdown-menu', @dropdown) + + if menu.hasClass(PAGE_TWO_CLASS) + if @remote + @remote.execute() + + menu.toggleClass PAGE_TWO_CLASS + + # Focus first visible input on active page + @dropdown.find('[class^="dropdown-page-"]:visible :text:visible:first').focus() + + parseData: (data) -> + @renderedData = data + + if @options.filterable and data.length is 0 + # render no matching results + html = [@noResults()] + else + # Handle array groups + if gl.utils.isObject data + html = [] + for name, groupData of data + # Add header for each group + html.push(@renderItem(header: name, name)) + + @renderData(groupData, name) + .map (item) -> + html.push item + else + # Render each row + html = @renderData(data) + + # Render the full menu + full_html = @renderMenu(html) + + @appendMenu(full_html) + + renderData: (data, group = false) -> + data.map (obj, index) => + return @renderItem(obj, group, index) + + shouldPropagate: (e) => + if @options.multiSelect + $target = $(e.target) + + if not $target.hasClass('dropdown-menu-close') and not $target.hasClass('dropdown-menu-close-icon') and not $target.data('is-link') + e.stopPropagation() + return false + else + return true + + opened: => + @resetRows() + @addArrowKeyEvent() + + if @options.setIndeterminateIds + @options.setIndeterminateIds.call(@) + + if @options.setActiveIds + @options.setActiveIds.call(@) + + # Makes indeterminate items effective + if @fullData and @dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update') + @parseData @fullData + + contentHtml = $('.dropdown-content', @dropdown).html() + if @remote && contentHtml is "" + @remote.execute() + + if @options.filterable + @filterInput.focus() + + @dropdown.trigger('shown.gl.dropdown') + + hidden: (e) => + @resetRows() + @removeArrayKeyEvent() + + $input = @dropdown.find(".dropdown-input-field") + + if @options.filterable + $input + .blur() + .val("") + + # Triggering 'keyup' will re-render the dropdown which is not always required + # specially if we want to keep the state of the dropdown needed for bulk-assignment + if not @options.persistWhenHide + $input.trigger("keyup") + + if @dropdown.find(".dropdown-toggle-page").length + $('.dropdown-menu', @dropdown).removeClass PAGE_TWO_CLASS + + if @options.hidden + @options.hidden.call(@,e) + + @dropdown.trigger('hidden.gl.dropdown') + + + # Render the full menu + renderMenu: (html) -> + menu_html = "" + + if @options.renderMenu + menu_html = @options.renderMenu(html) + else + menu_html = $('
    ') + .append(html) + + return menu_html + + # Append the menu into the dropdown + appendMenu: (html) -> + selector = '.dropdown-content' + if @dropdown.find(".dropdown-toggle-page").length + selector = ".dropdown-page-one .dropdown-content" + $(selector, @dropdown) + .empty() + .append(html) + + # Render the row + renderItem: (data, group = false, index = false) -> + html = "" + + # Divider + return "
  • " if data is "divider" + + # Separator is a full-width divider + return "
  • " if data is "separator" + + # Header + return _.template("") header: data.header if data.header? + + if @options.renderRow + # Call the render function + html = @options.renderRow.call(@options, data, @) + else + if not selected + value = if @options.id then @options.id(data) else data.id + fieldName = @options.fieldName + field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") + if field.length + selected = true + + # Set URL + if @options.url? + url = @options.url(data) + else + url = if data.url? then data.url else '#' + + # Set Text + if @options.text? + text = @options.text(data) + else + text = if data.text? then data.text else '' + + cssClass = "" + + if selected + cssClass = "is-active" + + if @highlight + text = @highlightTextMatches(text, @filterInput.val()) + + if group + groupAttrs = "data-group=#{group} data-index=#{index}" + else + groupAttrs = '' + html = _.template("
  • + class='<%- cssClass %>'> + <%= text %> + +
  • ")({ + url: url + groupAttrs: groupAttrs + cssClass: cssClass + text: text + }) + + return html + + highlightTextMatches: (text, term) -> + occurrences = fuzzaldrinPlus.match(text, term) + text.split('').map((character, i) -> + if i in occurrences then "#{character}" else character + ).join('') + + noResults: -> + html = "" + + rowClicked: (el) -> + fieldName = @options.fieldName + isInput = $(@el).is('input') + + if @renderedData + groupName = el.data('group') + if groupName + selectedIndex = el.data('index') + selectedObject = @renderedData[groupName][selectedIndex] + else + selectedIndex = el.closest('li').index() + selectedObject = @renderedData[selectedIndex] + + value = if @options.id then @options.id(selectedObject, el) else selectedObject.id + + if isInput + field = $(@el) + else + field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") + + if el.hasClass(ACTIVE_CLASS) + el.removeClass(ACTIVE_CLASS) + + if isInput + field.val('') + else + field.remove() + + # Toggle the dropdown label + if @options.toggleLabel + @updateLabel(selectedObject, el, @) + else + selectedObject + else if el.hasClass(INDETERMINATE_CLASS) + el.addClass ACTIVE_CLASS + el.removeClass INDETERMINATE_CLASS + + if not value? + field.remove() + + if not field.length and fieldName + @addInput(fieldName, value) + + return selectedObject + else + if not @options.multiSelect or el.hasClass('dropdown-clear-active') + @dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS + + unless isInput + @dropdown.parent().find("input[name='#{fieldName}']").remove() + + if !value? + field.remove() + + # Toggle active class for the tick mark + el.addClass ACTIVE_CLASS + + # Toggle the dropdown label + if @options.toggleLabel + @updateLabel(selectedObject, el, @) + if value? + if !field.length and fieldName + @addInput(fieldName, value) + else + field + .val value + .trigger 'change' + + return selectedObject + + addInput: (fieldName, value)-> + # Create hidden input for form + $input = $('').attr('type', 'hidden') + .attr('name', fieldName) + .val(value) + + if @options.inputId? + $input.attr('id', @options.inputId) + + @dropdown.before $input + + selectRowAtIndex: (e, index) -> + # Dropdown list item link selector, excluding non-selectable list items + selector = "#{SELECTABLE_CLASSES}:eq(#{index}) a" + + if @dropdown.find(".dropdown-toggle-page").length + selector = ".dropdown-page-one #{selector}" + + # simulate a click on the first link + $el = $(selector, @dropdown) + if $el.length + e.preventDefault() + e.stopImmediatePropagation() + $el.first().trigger 'click' + href = $el.attr 'href' + Turbolinks.visit(href) if href + + addArrowKeyEvent: -> + ARROW_KEY_CODES = [38, 40] + $input = @dropdown.find(".dropdown-input-field") + + # Dropdown list item selector, excluding non-selectable list items + selector = SELECTABLE_CLASSES + if @dropdown.find(".dropdown-toggle-page").length + selector = ".dropdown-page-one #{selector}" + + $('body').on 'keydown', (e) => + currentKeyCode = e.which + + if ARROW_KEY_CODES.indexOf(currentKeyCode) >= 0 + e.preventDefault() + e.stopImmediatePropagation() + + PREV_INDEX = currentIndex + $listItems = $(selector, @dropdown) + + # if @options.filterable + # $input.blur() + + if currentKeyCode is 40 + # Move down + currentIndex += 1 if currentIndex < ($listItems.length - 1) + else if currentKeyCode is 38 + # Move up + currentIndex -= 1 if currentIndex > 0 + + @highlightRowAtIndex($listItems, currentIndex) if currentIndex isnt PREV_INDEX + + return false + + # If enter is pressed and a row is highlighted, select it + if currentKeyCode is 13 and currentIndex != -1 + e.preventDefault() + e.stopImmediatePropagation() + @selectRowAtIndex e, currentIndex + + removeArrayKeyEvent: -> + $('body').off 'keydown' + + # Resets the currently selected item row index and removes all highlights + resetRows: -> + currentIndex = -1 + $('.is-focused', @dropdown).removeClass 'is-focused' + + highlightRowAtIndex: ($listItems, index) -> + # Remove the class for the previously focused row + $('.is-focused', @dropdown).removeClass 'is-focused' + + # Update the class for the row at the specific index + $listItem = $listItems.eq(index) + $listItem.find('a:first-child').addClass "is-focused" + + # Dropdown content scroll area + $dropdownContent = $listItem.closest('.dropdown-content') + dropdownScrollTop = $dropdownContent.scrollTop() + dropdownContentHeight = $dropdownContent.outerHeight() + dropdownContentTop = $dropdownContent.prop('offsetTop') + dropdownContentBottom = dropdownContentTop + dropdownContentHeight + + # Get the offset bottom of the list item + listItemHeight = $listItem.outerHeight() + listItemTop = $listItem.prop('offsetTop') + listItemBottom = listItemTop + listItemHeight + + if index is 0 + # If this is the first item in the list, scroll to the top + $dropdownContent.scrollTop(0) + else if index is $listItems.length - 1 + # If this is the last item in the list, scroll to the bottom + $dropdownContent.scrollTop($dropdownContent[0].scrollHeight) + else if listItemBottom > dropdownContentBottom + dropdownScrollTop + # Scroll the dropdown content down with a little padding + $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING) + else if listItemTop < dropdownContentTop + dropdownScrollTop + # Scroll the dropdown content up with a little padding + $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING) + + updateLabel: (selected = null, el = null, instance = null) => + $(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selected, el, instance) + +$.fn.glDropdown = (opts) -> + return @.each -> + if (!$.data @, 'glDropdown') + $.data(@, 'glDropdown', new GitLabDropdown @, opts) diff --git a/app/assets/javascripts/search_autocomplete.js.coffee b/app/assets/javascripts/search_autocomplete.js.coffee new file mode 100644 index 00000000000..a3baea1ae01 --- /dev/null +++ b/app/assets/javascripts/search_autocomplete.js.coffee @@ -0,0 +1,349 @@ +class @SearchAutocomplete + + KEYCODE = + ESCAPE: 27 + BACKSPACE: 8 + ENTER: 13 + UP: 38 + DOWN: 40 + + constructor: (opts = {}) -> + { + @wrap = $('.search') + + @optsEl = @wrap.find('.search-autocomplete-opts') + @autocompletePath = @optsEl.data('autocomplete-path') + @projectId = @optsEl.data('autocomplete-project-id') || '' + @projectRef = @optsEl.data('autocomplete-project-ref') || '' + + } = opts + + # Dropdown Element + @dropdown = @wrap.find('.dropdown') + @dropdownContent = @dropdown.find('.dropdown-content') + + @locationBadgeEl = @getElement('.location-badge') + @scopeInputEl = @getElement('#scope') + @searchInput = @getElement('.search-input') + @projectInputEl = @getElement('#search_project_id') + @groupInputEl = @getElement('#group_id') + @searchCodeInputEl = @getElement('#search_code') + @repositoryInputEl = @getElement('#repository_ref') + @clearInput = @getElement('.js-clear-input') + + @saveOriginalState() + + # Only when user is logged in + @createAutocomplete() if gon.current_user_id + + @searchInput.addClass('disabled') + + @saveTextLength() + + @bindEvents() + + # Finds an element inside wrapper element + getElement: (selector) -> + @wrap.find(selector) + + saveOriginalState: -> + @originalState = @serializeState() + + saveTextLength: -> + @lastTextLength = @searchInput.val().length + + createAutocomplete: -> + @searchInput.glDropdown + filterInputBlur: false + filterable: true + filterRemote: true + highlight: true + enterCallback: false + filterInput: 'input#search' + search: + fields: ['text'] + data: @getData.bind(@) + selectable: true + clicked: @onClick.bind(@) + + getData: (term, callback) -> + _this = @ + + unless term + if contents = @getCategoryContents() + @searchInput.data('glDropdown').filter.options.callback contents + @enableAutocomplete() + + return + + # Prevent multiple ajax calls + return if @loadingSuggestions + + @loadingSuggestions = true + + jqXHR = $.get(@autocompletePath, { + project_id: @projectId + project_ref: @projectRef + term: term + }, (response) -> + # Hide dropdown menu if no suggestions returns + if !response.length + _this.disableAutocomplete() + return + + data = [] + + # List results + firstCategory = true + for suggestion in response + + # Add group header before list each group + if lastCategory isnt suggestion.category + data.push 'separator' if !firstCategory + + firstCategory = false if firstCategory + + data.push + header: suggestion.category + + lastCategory = suggestion.category + + data.push + id: "#{suggestion.category.toLowerCase()}-#{suggestion.id}" + category: suggestion.category + text: suggestion.label + url: suggestion.url + + # Add option to proceed with the search + if data.length + data.push('separator') + data.push + text: "Result name contains \"#{term}\"" + url: "/search?\ + search=#{term}\ + &project_id=#{_this.projectInputEl.val()}\ + &group_id=#{_this.groupInputEl.val()}" + + callback(data) + ).always -> + _this.loadingSuggestions = false + + + getCategoryContents: -> + + userId = gon.current_user_id + { utils, projectOptions, groupOptions, dashboardOptions } = gl + + if utils.isInGroupsPage() and groupOptions + options = groupOptions[utils.getGroupSlug()] + + else if utils.isInProjectPage() and projectOptions + options = projectOptions[utils.getProjectSlug()] + + else if dashboardOptions + options = dashboardOptions + + { issuesPath, mrPath, name } = options + + items = [ + { header: "#{name}" } + { text: 'Issues assigned to me', url: "#{issuesPath}/?assignee_id=#{userId}" } + { text: "Issues I've created", url: "#{issuesPath}/?author_id=#{userId}" } + 'separator' + { text: 'Merge requests assigned to me', url: "#{mrPath}/?assignee_id=#{userId}" } + { text: "Merge requests I've created", url: "#{mrPath}/?author_id=#{userId}" } + ] + + items.splice 0, 1 unless name + + return items + + + serializeState: -> + { + # Search Criteria + search_project_id: @projectInputEl.val() + group_id: @groupInputEl.val() + search_code: @searchCodeInputEl.val() + repository_ref: @repositoryInputEl.val() + scope: @scopeInputEl.val() + + # Location badge + _location: @locationBadgeEl.text() + } + + bindEvents: -> + @searchInput.on 'keydown', @onSearchInputKeyDown + @searchInput.on 'keyup', @onSearchInputKeyUp + @searchInput.on 'click', @onSearchInputClick + @searchInput.on 'focus', @onSearchInputFocus + @searchInput.on 'blur', @onSearchInputBlur + @clearInput.on 'click', @onClearInputClick + @locationBadgeEl.on 'click', => + @searchInput.focus() + + enableAutocomplete: -> + # No need to enable anything if user is not logged in + return if !gon.current_user_id + + unless @dropdown.hasClass('open') + _this = @ + @loadingSuggestions = false + + # If not enabled already, enable + if not @dropdown.hasClass('open') + # Open dropdown and invoke its opened() method + @dropdown.addClass('open') + .trigger('shown.bs.dropdown') + @searchInput.removeClass('disabled') + + onSearchInputKeyDown: => + # Saves last length of the entered text + @saveTextLength() + + onSearchInputKeyUp: (e) => + switch e.keyCode + when KEYCODE.BACKSPACE + # when trying to remove the location badge + if @lastTextLength is 0 and @badgePresent() + @removeLocationBadge() + + # When removing the last character and no badge is present + if @lastTextLength is 1 + @disableAutocomplete() + + # When removing any character from existin value + if @lastTextLength > 1 + @enableAutocomplete() + + when KEYCODE.ESCAPE + @restoreOriginalState() + + # Close autocomplete on enter + when KEYCODE.ENTER + @disableAutocomplete() + + when KEYCODE.UP, KEYCODE.DOWN + return + + else + # Handle the case when deleting the input value other than backspace + # e.g. Pressing ctrl + backspace or ctrl + x + if @searchInput.val() is '' + @disableAutocomplete() + else + # We should display the menu only when input is not empty + @enableAutocomplete() + + @wrap.toggleClass 'has-value', !!e.target.value + + # Avoid falsy value to be returned + return + + onSearchInputClick: (e) => + # Prevents closing the dropdown menu + e.stopImmediatePropagation() + + onSearchInputFocus: => + @isFocused = true + @wrap.addClass('search-active') + + @getData() if @getValue() is '' + + + getValue: -> return @searchInput.val() + + + onClearInputClick: (e) => + e.preventDefault() + @searchInput.val('').focus() + + onSearchInputBlur: (e) => + @isFocused = false + @wrap.removeClass('search-active') + + # If input is blank then restore state + if @searchInput.val() is '' + @restoreOriginalState() + + addLocationBadge: (item) -> + category = if item.category? then "#{item.category}: " else '' + value = if item.value? then item.value else '' + + badgeText = "#{category}#{value}" + @locationBadgeEl.text(badgeText).show() + @wrap.addClass('has-location-badge') + + + hasLocationBadge: -> return @wrap.is '.has-location-badge' + + + restoreOriginalState: -> + inputs = Object.keys @originalState + + for input in inputs + @getElement("##{input}").val(@originalState[input]) + + if @originalState._location is '' + @locationBadgeEl.hide() + else + @addLocationBadge( + value: @originalState._location + ) + + badgePresent: -> + @locationBadgeEl.length + + resetSearchState: -> + inputs = Object.keys @originalState + + for input in inputs + + # _location isnt a input + break if input is '_location' + + @getElement("##{input}").val('') + + + removeLocationBadge: -> + + @locationBadgeEl.hide() + @resetSearchState() + @wrap.removeClass('has-location-badge') + @disableAutocomplete() + + + disableAutocomplete: -> + # If not disabled already, disable + if not @searchInput.hasClass('disabled') && @dropdown.hasClass('open') + @searchInput.addClass('disabled') + # Close dropdown and invoke its hidden() method + @dropdown.removeClass('open') + .trigger('hidden.bs.dropdown') + @restoreMenu() + + restoreMenu: -> + html = "" + @dropdownContent.html(html) + + onClick: (item, $el, e) -> + if location.pathname.indexOf(item.url) isnt -1 + e.preventDefault() + if not @badgePresent + if item.category is 'Projects' + @projectInputEl.val(item.id) + @addLocationBadge( + value: 'This project' + ) + + if item.category is 'Groups' + @groupInputEl.val(item.id) + @addLocationBadge( + value: 'This group' + ) + + $el.removeClass('is-active') + @disableAutocomplete() + @searchInput.val('').focus() -- cgit v1.2.1 From 85cd73c768b57aa13b1cd6fc75b5c855b0b8fe89 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Thu, 7 Jul 2016 15:08:34 +0100 Subject: improved turbolinks.visit conditional --- app/assets/javascripts/gl_dropdown.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index e096effaade..7a4224d9032 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -566,7 +566,7 @@ class GitLabDropdown e.stopImmediatePropagation() $el.first().trigger 'click' href = $el.attr 'href' - Turbolinks.visit(href) if href + Turbolinks.visit(href) if href and href isnt '#' addArrowKeyEvent: -> ARROW_KEY_CODES = [38, 40] -- cgit v1.2.1 From 40d869eefa2c491446b6aa75ec1337add6ce3e4a Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Thu, 7 Jul 2016 22:18:40 +0100 Subject: Review changes and final formatting --- app/assets/javascripts/gl_dropdown.js.coffee | 255 ++++++++++++--------------- 1 file changed, 115 insertions(+), 140 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index 7a4224d9032..4e439e0de84 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -1,7 +1,7 @@ class GitLabDropdownFilter BLUR_KEYCODES = [27, 40] ARROW_KEY_CODES = [38, 40] - HAS_VALUE_CLASS = "has-value" + HAS_VALUE_CLASS = 'has-value' constructor: (@input, @options) -> { @@ -9,7 +9,7 @@ class GitLabDropdownFilter } = @options $inputContainer = @input.parent() - $clearButton = $inputContainer.find('.js-dropdown-input-clear') + $clearButton = $inputContainer.find '.js-dropdown-input-clear' @indeterminateIds = [] @@ -18,24 +18,23 @@ class GitLabDropdownFilter e.preventDefault() e.stopPropagation() @input - .val('') - .trigger('keyup') + .val '' + .trigger 'keyup' .focus() # Key events - timeout = "" - @input.on "keyup", (e) => + timeout = '' + @input.on 'keyup', (e) => keyCode = e.which return if ARROW_KEY_CODES.indexOf(keyCode) >= 0 - if @input.val() isnt "" and !$inputContainer.hasClass HAS_VALUE_CLASS + if @input.val() isnt '' and not $inputContainer.hasClass HAS_VALUE_CLASS $inputContainer.addClass HAS_VALUE_CLASS - else if @input.val() is "" and $inputContainer.hasClass HAS_VALUE_CLASS + else if @input.val() is '' and $inputContainer.hasClass HAS_VALUE_CLASS $inputContainer.removeClass HAS_VALUE_CLASS - if keyCode is 13 - return false + return false if keyCode is 13 # Only filter asynchronously only if option remote is set if @options.remote @@ -47,13 +46,13 @@ class GitLabDropdownFilter @input.blur() @options.query @input.val(), (data) => - @options.callback(data) + @options.callback data , 250 else @filter @input.val() shouldBlur: (keyCode) -> - return BLUR_KEYCODES.indexOf(keyCode) >= 0 + BLUR_KEYCODES.indexOf(keyCode) >= 0 filter: (search_text) -> @options.onFilter(search_text) if @options.onFilter @@ -69,9 +68,8 @@ class GitLabDropdownFilter # { prop: 'baz' } # ] if _.isArray(data) - results = fuzzaldrinPlus.filter(data, search_text, + results = fuzzaldrinPlus.filter data, search_text, key: @options.keys - ) else # If data is grouped therefore an [object Object]. e.g. # { @@ -87,9 +85,8 @@ class GitLabDropdownFilter if gl.utils.isObject data results = {} for key, group of data - tmp = fuzzaldrinPlus.filter(group, search_text, + tmp = fuzzaldrinPlus.filter group, search_text, key: @options.keys - ) if tmp.length results[key] = tmp.map (item) -> item @@ -100,10 +97,10 @@ class GitLabDropdownFilter if search_text elements.each -> - $el = $(@) - matches = fuzzaldrinPlus.match($el.text().trim(), search_text) + $el = $(this) + matches = fuzzaldrinPlus.match $el.text().trim(), search_text - unless $el.is('.dropdown-header') + unless $el.is '.dropdown-header' if matches.length $el.show() else @@ -115,38 +112,31 @@ class GitLabDropdownRemote constructor: (@dataEndpoint, @options) -> execute: -> - if typeof @dataEndpoint is "string" + if typeof @dataEndpoint is 'string' @fetchData() - else if typeof @dataEndpoint is "function" - if @options.beforeSend - @options.beforeSend() + else if typeof @dataEndpoint is 'function' + @options.beforeSend() if @options.beforeSend # Fetch the data by calling the data funcfion - @dataEndpoint "", (data) => - if @options.success - @options.success(data) - - if @options.beforeSend - @options.beforeSend() + @dataEndpoint '', (data) => + @options.success(data) if @options.success + @options.beforeSend() if @options.beforeSend # Fetch the data through ajax if the data is a string fetchData: -> - $.ajax( + $.ajax url: @dataEndpoint, dataType: @options.dataType, beforeSend: => - if @options.beforeSend - @options.beforeSend() + @options.beforeSend() if @options.beforeSend success: (data) => - if @options.success - @options.success(data) - ) + @options.success(data) if @options.success class GitLabDropdown - LOADING_CLASS = "is-loading" - PAGE_TWO_CLASS = "is-page-two" - ACTIVE_CLASS = "is-active" - INDETERMINATE_CLASS = "is-indeterminate" + LOADING_CLASS = 'is-loading' + PAGE_TWO_CLASS = 'is-page-two' + ACTIVE_CLASS = 'is-active' + INDETERMINATE_CLASS = 'is-indeterminate' NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link' SELECTABLE_CLASSES = ".dropdown-content li:not(#{NON_SELECTABLE_CLASSES})" FILTER_INPUT = '.dropdown-input .dropdown-input-field' @@ -154,37 +144,36 @@ class GitLabDropdown CURSOR_SELECT_SCROLL_PADDING = 5 constructor: (@el, @options) -> - self = @ - selector = $(@el).data "target" + self = this + selector = $(@el).data 'target' @dropdown = if selector? then $(selector) else $(@el).parent() # Set Defaults { # If no input is passed create a default one - @filterInput = @getElement(FILTER_INPUT) + @filterInput = @getElement FILTER_INPUT @highlight = false @filterInputBlur = true } = @options - self = @ + self = this # If selector was passed - if _.isString(@filterInput) - @filterInput = @getElement(@filterInput) + @filterInput = @getElement(@filterInput) if _.isString @filterInput searchFields = if @options.search then @options.search.fields else [] if @options.data # If we provided data # data could be an array of objects or a group of arrays - if _.isObject(@options.data) and not _.isFunction(@options.data) + if _.isObject(@options.data) and not _.isFunction @options.data @fullData = @options.data @parseData @options.data else # Remote data - @remote = new GitLabDropdownRemote @options.data, { + @remote = new GitLabDropdownRemote @options.data, dataType: @options.dataType, - beforeSend: @toggleLoading.bind(@) + beforeSend: @toggleLoading.bind this success: (data) => @fullData = data @@ -192,8 +181,8 @@ class GitLabDropdown currentIndex = -1 @parseData @fullData - @filter.input.trigger('keyup') if @options.filterable and @filter and @filter.input - } + if @options.filterable and @filter and @filter.input + @filter.input.trigger 'keyup' # Init filterable if @options.filterable @@ -210,9 +199,9 @@ class GitLabDropdown if @dropdown.find('.dropdown-toggle-page').length selector = ".dropdown-page-one #{selector}" - return $(selector) + $(selector) data: => - return @fullData + @fullData callback: (data) => @parseData data @@ -232,36 +221,35 @@ class GitLabDropdown # Event listeners - @dropdown.on "shown.bs.dropdown", @opened - @dropdown.on "hidden.bs.dropdown", @hidden - $(@el).on "update.label", @updateLabel - @dropdown.on "click", ".dropdown-menu, .dropdown-menu-close", @shouldPropagate + @dropdown.on 'shown.bs.dropdown', @opened + @dropdown.on 'hidden.bs.dropdown', @hidden + $(@el).on 'update.label', @updateLabel + @dropdown.on 'click', '.dropdown-menu, .dropdown-menu-close', @shouldPropagate @dropdown.on 'keyup', (e) => - if e.which is 27 # Escape key - $('.dropdown-menu-close', @dropdown).trigger 'click' + $('.dropdown-menu-close', @dropdown).trigger 'click' if e.which is 27 + @dropdown.on 'blur', 'a', (e) => if e.relatedTarget? $relatedTarget = $(e.relatedTarget) $dropdownMenu = $relatedTarget.closest('.dropdown-menu') - if $dropdownMenu.length is 0 - @dropdown.removeClass('open') + @dropdown.removeClass('open') if $dropdownMenu.length is 0 - if @dropdown.find(".dropdown-toggle-page").length - @dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on "click", (e) => + if @dropdown.find('.dropdown-toggle-page').length + @dropdown.find('.dropdown-toggle-page, .dropdown-menu-back').on 'click', (e) => e.preventDefault() e.stopPropagation() @togglePage() if @options.selectable - selector = ".dropdown-content a" + selector = '.dropdown-content a' - if @dropdown.find(".dropdown-toggle-page").length - selector = ".dropdown-page-one .dropdown-content a" + if @dropdown.find('.dropdown-toggle-page').length + selector = '.dropdown-page-one .dropdown-content a' - @dropdown.on "click", selector, (e) -> - $el = $(@) + @dropdown.on 'click', selector, (e) -> + $el = $(this) selected = self.rowClicked $el if self.options.clicked @@ -280,8 +268,7 @@ class GitLabDropdown menu = $('.dropdown-menu', @dropdown) if menu.hasClass(PAGE_TWO_CLASS) - if @remote - @remote.execute() + @remote.execute() if @remote menu.toggleClass PAGE_TWO_CLASS @@ -316,38 +303,32 @@ class GitLabDropdown renderData: (data, group = false) -> data.map (obj, index) => - return @renderItem(obj, group, index) + @renderItem(obj, group, index) shouldPropagate: (e) => - if @options.multiSelect - $target = $(e.target) - - if not $target.hasClass('dropdown-menu-close') and not $target.hasClass('dropdown-menu-close-icon') and not $target.data('is-link') - e.stopPropagation() - return false - else - return true + $target = $(e.target) if @options.multiSelect + unless $target.hasClass('dropdown-menu-close') and $target.hasClass('dropdown-menu-close-icon') and $target.data('is-link') + e.stopPropagation() + false + else + true opened: => @resetRows() @addArrowKeyEvent() - if @options.setIndeterminateIds - @options.setIndeterminateIds.call(@) + @options.setIndeterminateIds.call this if @options.setIndeterminateIds - if @options.setActiveIds - @options.setActiveIds.call(@) + @options.setActiveIds.call this if @options.setActiveIds # Makes indeterminate items effective if @fullData and @dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update') @parseData @fullData contentHtml = $('.dropdown-content', @dropdown).html() - if @remote && contentHtml is "" - @remote.execute() + @remote.execute() if @remote and contentHtml is '' - if @options.filterable - @filterInput.focus() + @filterInput.focus() if @options.filterable @dropdown.trigger('shown.gl.dropdown') @@ -355,71 +336,67 @@ class GitLabDropdown @resetRows() @removeArrayKeyEvent() - $input = @dropdown.find(".dropdown-input-field") + $input = @dropdown.find('.dropdown-input-field') if @options.filterable $input .blur() - .val("") + .val('') # Triggering 'keyup' will re-render the dropdown which is not always required # specially if we want to keep the state of the dropdown needed for bulk-assignment - if not @options.persistWhenHide - $input.trigger("keyup") + $input.trigger('keyup') unless @options.persistWhenHide - if @dropdown.find(".dropdown-toggle-page").length + if @dropdown.find('.dropdown-toggle-page').length $('.dropdown-menu', @dropdown).removeClass PAGE_TWO_CLASS - if @options.hidden - @options.hidden.call(@,e) + @options.hidden.call this, e if @options.hidden @dropdown.trigger('hidden.gl.dropdown') # Render the full menu renderMenu: (html) -> - menu_html = "" + menu_html = '' if @options.renderMenu - menu_html = @options.renderMenu(html) + menu_html = @options.renderMenu html else - menu_html = $('
      ') - .append(html) + menu_html = $('
        ').append html - return menu_html + menu_html # Append the menu into the dropdown appendMenu: (html) -> selector = '.dropdown-content' - if @dropdown.find(".dropdown-toggle-page").length - selector = ".dropdown-page-one .dropdown-content" + if @dropdown.find('.dropdown-toggle-page').length + selector = '.dropdown-page-one .dropdown-content' $(selector, @dropdown) .empty() - .append(html) + .append html # Render the row renderItem: (data, group = false, index = false) -> - html = "" + html = '' # Divider - return "
      • " if data is "divider" + return '
      • ' if data is 'divider' # Separator is a full-width divider - return "
      • " if data is "separator" + return '
      • ' if data is 'separator' # Header - return _.template("") header: data.header if data.header? + return _.template('')({ header: data.header }) if data.header? if @options.renderRow # Call the render function html = @options.renderRow.call(@options, data, @) else - if not selected + unless selected value = if @options.id then @options.id(data) else data.id fieldName = @options.fieldName field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") - if field.length - selected = true + selected = true if field.length # Set URL if @options.url? @@ -433,10 +410,9 @@ class GitLabDropdown else text = if data.text? then data.text else '' - cssClass = "" + cssClass = '' - if selected - cssClass = "is-active" + cssClass = 'is-active' if selected if @highlight text = @highlightTextMatches(text, @filterInput.val()) @@ -445,18 +421,18 @@ class GitLabDropdown groupAttrs = "data-group=#{group} data-index=#{index}" else groupAttrs = '' - html = _.template("
      • - class='<%- cssClass %>'> + html = _.template('
      • + class="<%- cssClass %>"> <%= text %> -
      • ")({ + ')({ url: url groupAttrs: groupAttrs cssClass: cssClass text: text }) - return html + html highlightTextMatches: (text, term) -> occurrences = fuzzaldrinPlus.match(text, term) @@ -465,20 +441,20 @@ class GitLabDropdown ).join('') noResults: -> - html = "" + ' rowClicked: (el) -> fieldName = @options.fieldName isInput = $(@el).is('input') if @renderedData - groupName = el.data('group') + groupName = el.data 'group' if groupName - selectedIndex = el.data('index') + selectedIndex = el.data 'index' selectedObject = @renderedData[groupName][selectedIndex] else selectedIndex = el.closest('li').index() @@ -501,20 +477,19 @@ class GitLabDropdown # Toggle the dropdown label if @options.toggleLabel - @updateLabel(selectedObject, el, @) + @updateLabel(selectedObject, el, this) else selectedObject else if el.hasClass(INDETERMINATE_CLASS) el.addClass ACTIVE_CLASS el.removeClass INDETERMINATE_CLASS - if not value? - field.remove() + field.remove() unless value? if not field.length and fieldName @addInput(fieldName, value) - return selectedObject + selectedObject else if not @options.multiSelect or el.hasClass('dropdown-clear-active') @dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS @@ -522,24 +497,23 @@ class GitLabDropdown unless isInput @dropdown.parent().find("input[name='#{fieldName}']").remove() - if !value? - field.remove() + field.remove() unless value? # Toggle active class for the tick mark el.addClass ACTIVE_CLASS # Toggle the dropdown label if @options.toggleLabel - @updateLabel(selectedObject, el, @) + @updateLabel(selectedObject, el, this) if value? - if !field.length and fieldName + if not field.length and fieldName @addInput(fieldName, value) else field .val value .trigger 'change' - return selectedObject + selectedObject addInput: (fieldName, value)-> # Create hidden input for form @@ -556,7 +530,7 @@ class GitLabDropdown # Dropdown list item link selector, excluding non-selectable list items selector = "#{SELECTABLE_CLASSES}:eq(#{index}) a" - if @dropdown.find(".dropdown-toggle-page").length + if @dropdown.find('.dropdown-toggle-page').length selector = ".dropdown-page-one #{selector}" # simulate a click on the first link @@ -570,11 +544,11 @@ class GitLabDropdown addArrowKeyEvent: -> ARROW_KEY_CODES = [38, 40] - $input = @dropdown.find(".dropdown-input-field") + $input = @dropdown.find '.dropdown-input-field' # Dropdown list item selector, excluding non-selectable list items selector = SELECTABLE_CLASSES - if @dropdown.find(".dropdown-toggle-page").length + if @dropdown.find('.dropdown-toggle-page').length selector = ".dropdown-page-one #{selector}" $('body').on 'keydown', (e) => @@ -597,12 +571,13 @@ class GitLabDropdown # Move up currentIndex -= 1 if currentIndex > 0 - @highlightRowAtIndex($listItems, currentIndex) if currentIndex isnt PREV_INDEX + if currentIndex isnt PREV_INDEX + @highlightRowAtIndex($listItems, currentIndex) return false # If enter is pressed and a row is highlighted, select it - if currentKeyCode is 13 and currentIndex != -1 + if currentKeyCode is 13 and currentIndex isnt -1 e.preventDefault() e.stopImmediatePropagation() @selectRowAtIndex e, currentIndex @@ -621,7 +596,7 @@ class GitLabDropdown # Update the class for the row at the specific index $listItem = $listItems.eq(index) - $listItem.find('a:first-child').addClass "is-focused" + $listItem.find('a:first-child').addClass 'is-focused' # Dropdown content scroll area $dropdownContent = $listItem.closest('.dropdown-content') @@ -640,7 +615,7 @@ class GitLabDropdown $dropdownContent.scrollTop(0) else if index is $listItems.length - 1 # If this is the last item in the list, scroll to the bottom - $dropdownContent.scrollTop($dropdownContent[0].scrollHeight) + $dropdownContent.scrollTop $dropdownContent.prop 'scrollHeight' else if listItemBottom > dropdownContentBottom + dropdownScrollTop # Scroll the dropdown content down with a little padding $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING) @@ -649,9 +624,9 @@ class GitLabDropdown $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING) updateLabel: (selected = null, el = null, instance = null) => - $(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selected, el, instance) + $(@el).find('.dropdown-toggle-text').text @options.toggleLabel(selected, el, instance) $.fn.glDropdown = (opts) -> - return @.each -> - if (!$.data @, 'glDropdown') - $.data(@, 'glDropdown', new GitLabDropdown @, opts) + @each -> + unless $.data this, 'glDropdown' + $.data this, 'glDropdown', new GitLabDropdown this, opts -- cgit v1.2.1 From 1ac5f764cecdeaa4b41a77353a979f941cf0e72b Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Fri, 8 Jul 2016 02:00:45 +0100 Subject: Fixed test turbolink condition --- app/assets/javascripts/gl_dropdown.js.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index 4e439e0de84..5e626b148f3 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -307,7 +307,7 @@ class GitLabDropdown shouldPropagate: (e) => $target = $(e.target) if @options.multiSelect - unless $target.hasClass('dropdown-menu-close') and $target.hasClass('dropdown-menu-close-icon') and $target.data('is-link') + if $target and not $target.hasClass('dropdown-menu-close') and not $target.hasClass('dropdown-menu-close-icon') and not $target.data('is-link') e.stopPropagation() false else @@ -380,10 +380,10 @@ class GitLabDropdown html = '' # Divider - return '
      • ' if data is 'divider' + return '
      • ' if data is 'divider' # Separator is a full-width divider - return '
      • ' if data is 'separator' + return '
      • ' if data is 'separator' # Header return _.template('')({ header: data.header }) if data.header? @@ -518,8 +518,8 @@ class GitLabDropdown addInput: (fieldName, value)-> # Create hidden input for form $input = $('').attr('type', 'hidden') - .attr('name', fieldName) - .val(value) + .attr('name', fieldName) + .val(value) if @options.inputId? $input.attr('id', @options.inputId) -- cgit v1.2.1 From affdf201d2acb7ae582df89ee6013f5563925877 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Tue, 19 Jul 2016 13:15:14 +0100 Subject: Further review changes and removed large ammounts of reformatting --- app/assets/javascripts/gl_dropdown.js.coffee | 234 ++++++++++++--------- .../javascripts/search_autocomplete.js.coffee | 5 +- 2 files changed, 132 insertions(+), 107 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index 5e626b148f3..51f739ae201 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -1,7 +1,7 @@ class GitLabDropdownFilter BLUR_KEYCODES = [27, 40] ARROW_KEY_CODES = [38, 40] - HAS_VALUE_CLASS = 'has-value' + HAS_VALUE_CLASS = "has-value" constructor: (@input, @options) -> { @@ -9,7 +9,7 @@ class GitLabDropdownFilter } = @options $inputContainer = @input.parent() - $clearButton = $inputContainer.find '.js-dropdown-input-clear' + $clearButton = $inputContainer.find('.js-dropdown-input-clear') @indeterminateIds = [] @@ -18,23 +18,24 @@ class GitLabDropdownFilter e.preventDefault() e.stopPropagation() @input - .val '' - .trigger 'keyup' + .val('') + .trigger('keyup') .focus() # Key events - timeout = '' - @input.on 'keyup', (e) => + timeout = "" + @input.on "keyup", (e) => keyCode = e.which return if ARROW_KEY_CODES.indexOf(keyCode) >= 0 - if @input.val() isnt '' and not $inputContainer.hasClass HAS_VALUE_CLASS + if @input.val() isnt "" and !$inputContainer.hasClass HAS_VALUE_CLASS $inputContainer.addClass HAS_VALUE_CLASS - else if @input.val() is '' and $inputContainer.hasClass HAS_VALUE_CLASS + else if @input.val() is "" and $inputContainer.hasClass HAS_VALUE_CLASS $inputContainer.removeClass HAS_VALUE_CLASS - return false if keyCode is 13 + if keyCode is 13 + return false # Only filter asynchronously only if option remote is set if @options.remote @@ -46,13 +47,13 @@ class GitLabDropdownFilter @input.blur() @options.query @input.val(), (data) => - @options.callback data + @options.callback(data) , 250 else @filter @input.val() shouldBlur: (keyCode) -> - BLUR_KEYCODES.indexOf(keyCode) >= 0 + return BLUR_KEYCODES.indexOf(keyCode) >= 0 filter: (search_text) -> @options.onFilter(search_text) if @options.onFilter @@ -68,8 +69,9 @@ class GitLabDropdownFilter # { prop: 'baz' } # ] if _.isArray(data) - results = fuzzaldrinPlus.filter data, search_text, + results = fuzzaldrinPlus.filter(data, search_text, key: @options.keys + ) else # If data is grouped therefore an [object Object]. e.g. # { @@ -85,8 +87,9 @@ class GitLabDropdownFilter if gl.utils.isObject data results = {} for key, group of data - tmp = fuzzaldrinPlus.filter group, search_text, + tmp = fuzzaldrinPlus.filter(group, search_text, key: @options.keys + ) if tmp.length results[key] = tmp.map (item) -> item @@ -97,10 +100,10 @@ class GitLabDropdownFilter if search_text elements.each -> - $el = $(this) - matches = fuzzaldrinPlus.match $el.text().trim(), search_text + $el = $(@) + matches = fuzzaldrinPlus.match($el.text().trim(), search_text) - unless $el.is '.dropdown-header' + unless $el.is('.dropdown-header') if matches.length $el.show() else @@ -112,68 +115,75 @@ class GitLabDropdownRemote constructor: (@dataEndpoint, @options) -> execute: -> - if typeof @dataEndpoint is 'string' + if typeof @dataEndpoint is "string" @fetchData() - else if typeof @dataEndpoint is 'function' - @options.beforeSend() if @options.beforeSend + else if typeof @dataEndpoint is "function" + if @options.beforeSend + @options.beforeSend() # Fetch the data by calling the data funcfion - @dataEndpoint '', (data) => - @options.success(data) if @options.success - @options.beforeSend() if @options.beforeSend + @dataEndpoint "", (data) => + if @options.success + @options.success(data) + if @options.beforeSend + @options.beforeSend() # Fetch the data through ajax if the data is a string fetchData: -> - $.ajax + $.ajax( url: @dataEndpoint, dataType: @options.dataType, beforeSend: => - @options.beforeSend() if @options.beforeSend + if @options.beforeSend + @options.beforeSend() success: (data) => - @options.success(data) if @options.success + if @options.success + @options.success(data) + ) class GitLabDropdown - LOADING_CLASS = 'is-loading' - PAGE_TWO_CLASS = 'is-page-two' - ACTIVE_CLASS = 'is-active' - INDETERMINATE_CLASS = 'is-indeterminate' + LOADING_CLASS = "is-loading" + PAGE_TWO_CLASS = "is-page-two" + ACTIVE_CLASS = "is-active" + INDETERMINATE_CLASS = "is-indeterminate" + currentIndex = -1 NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link' SELECTABLE_CLASSES = ".dropdown-content li:not(#{NON_SELECTABLE_CLASSES})" FILTER_INPUT = '.dropdown-input .dropdown-input-field' - currentIndex = -1 CURSOR_SELECT_SCROLL_PADDING = 5 constructor: (@el, @options) -> - self = this - selector = $(@el).data 'target' + self = @ + selector = $(@el).data "target" @dropdown = if selector? then $(selector) else $(@el).parent() # Set Defaults { # If no input is passed create a default one - @filterInput = @getElement FILTER_INPUT + @filterInput = @getElement(FILTER_INPUT) @highlight = false @filterInputBlur = true } = @options - self = this + self = @ # If selector was passed - @filterInput = @getElement(@filterInput) if _.isString @filterInput + if _.isString(@filterInput) + @filterInput = @getElement(@filterInput) searchFields = if @options.search then @options.search.fields else [] if @options.data # If we provided data # data could be an array of objects or a group of arrays - if _.isObject(@options.data) and not _.isFunction @options.data + if _.isObject(@options.data) and not _.isFunction(@options.data) @fullData = @options.data @parseData @options.data else # Remote data - @remote = new GitLabDropdownRemote @options.data, + @remote = new GitLabDropdownRemote @options.data, { dataType: @options.dataType, - beforeSend: @toggleLoading.bind this + beforeSend: @toggleLoading.bind(@) success: (data) => @fullData = data @@ -181,8 +191,8 @@ class GitLabDropdown currentIndex = -1 @parseData @fullData - if @options.filterable and @filter and @filter.input - @filter.input.trigger 'keyup' + @filter.input.trigger('keyup') if @options.filterable and @filter and @filter.input + } # Init filterable if @options.filterable @@ -199,9 +209,9 @@ class GitLabDropdown if @dropdown.find('.dropdown-toggle-page').length selector = ".dropdown-page-one #{selector}" - $(selector) + return $(selector) data: => - @fullData + return @fullData callback: (data) => @parseData data @@ -221,35 +231,37 @@ class GitLabDropdown # Event listeners - @dropdown.on 'shown.bs.dropdown', @opened - @dropdown.on 'hidden.bs.dropdown', @hidden - $(@el).on 'update.label', @updateLabel - @dropdown.on 'click', '.dropdown-menu, .dropdown-menu-close', @shouldPropagate + @dropdown.on "shown.bs.dropdown", @opened + @dropdown.on "hidden.bs.dropdown", @hidden + $(@el).on "update.label", @updateLabel + @dropdown.on "click", ".dropdown-menu, .dropdown-menu-close", @shouldPropagate @dropdown.on 'keyup', (e) => - $('.dropdown-menu-close', @dropdown).trigger 'click' if e.which is 27 + if e.which is 27 # Escape key + $('.dropdown-menu-close', @dropdown).trigger 'click' @dropdown.on 'blur', 'a', (e) => if e.relatedTarget? $relatedTarget = $(e.relatedTarget) $dropdownMenu = $relatedTarget.closest('.dropdown-menu') - @dropdown.removeClass('open') if $dropdownMenu.length is 0 + if $dropdownMenu.length is 0 + @dropdown.removeClass('open') - if @dropdown.find('.dropdown-toggle-page').length - @dropdown.find('.dropdown-toggle-page, .dropdown-menu-back').on 'click', (e) => + if @dropdown.find(".dropdown-toggle-page").length + @dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on "click", (e) => e.preventDefault() e.stopPropagation() @togglePage() if @options.selectable - selector = '.dropdown-content a' + selector = ".dropdown-content a" - if @dropdown.find('.dropdown-toggle-page').length - selector = '.dropdown-page-one .dropdown-content a' + if @dropdown.find(".dropdown-toggle-page").length + selector = ".dropdown-page-one .dropdown-content a" - @dropdown.on 'click', selector, (e) -> - $el = $(this) + @dropdown.on "click", selector, (e) -> + $el = $(@) selected = self.rowClicked $el if self.options.clicked @@ -268,7 +280,8 @@ class GitLabDropdown menu = $('.dropdown-menu', @dropdown) if menu.hasClass(PAGE_TWO_CLASS) - @remote.execute() if @remote + if @remote + @remote.execute() menu.toggleClass PAGE_TWO_CLASS @@ -303,32 +316,38 @@ class GitLabDropdown renderData: (data, group = false) -> data.map (obj, index) => - @renderItem(obj, group, index) + return @renderItem(obj, group, index) shouldPropagate: (e) => - $target = $(e.target) if @options.multiSelect + if @options.multiSelect + $target = $(e.target) + if $target and not $target.hasClass('dropdown-menu-close') and not $target.hasClass('dropdown-menu-close-icon') and not $target.data('is-link') e.stopPropagation() - false + return false else - true + return true opened: => @resetRows() @addArrowKeyEvent() - @options.setIndeterminateIds.call this if @options.setIndeterminateIds + if @options.setIndeterminateIds + @options.setIndeterminateIds.call(@) - @options.setActiveIds.call this if @options.setActiveIds + if @options.setActiveIds + @options.setActiveIds.call(@) # Makes indeterminate items effective if @fullData and @dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update') @parseData @fullData contentHtml = $('.dropdown-content', @dropdown).html() - @remote.execute() if @remote and contentHtml is '' + if @remote && contentHtml is "" + @remote.execute() - @filterInput.focus() if @options.filterable + if @options.filterable + @filterInput.focus() @dropdown.trigger('shown.gl.dropdown') @@ -336,48 +355,51 @@ class GitLabDropdown @resetRows() @removeArrayKeyEvent() - $input = @dropdown.find('.dropdown-input-field') + $input = @dropdown.find(".dropdown-input-field") if @options.filterable $input .blur() - .val('') + .val("") # Triggering 'keyup' will re-render the dropdown which is not always required # specially if we want to keep the state of the dropdown needed for bulk-assignment - $input.trigger('keyup') unless @options.persistWhenHide + if not @options.persistWhenHide + $input.trigger("keyup") - if @dropdown.find('.dropdown-toggle-page').length + if @dropdown.find(".dropdown-toggle-page").length $('.dropdown-menu', @dropdown).removeClass PAGE_TWO_CLASS - @options.hidden.call this, e if @options.hidden + if @options.hidden + @options.hidden.call(@,e) @dropdown.trigger('hidden.gl.dropdown') # Render the full menu renderMenu: (html) -> - menu_html = '' + menu_html = "" if @options.renderMenu - menu_html = @options.renderMenu html + menu_html = @options.renderMenu(html) else - menu_html = $('
          ').append html + menu_html = $('
            ') + .append(html) - menu_html + return menu_html # Append the menu into the dropdown appendMenu: (html) -> selector = '.dropdown-content' - if @dropdown.find('.dropdown-toggle-page').length - selector = '.dropdown-page-one .dropdown-content' + if @dropdown.find(".dropdown-toggle-page").length + selector = ".dropdown-page-one .dropdown-content" $(selector, @dropdown) .empty() - .append html + .append(html) # Render the row renderItem: (data, group = false, index = false) -> - html = '' + html = "" # Divider return '
          • ' if data is 'divider' @@ -392,11 +414,12 @@ class GitLabDropdown # Call the render function html = @options.renderRow.call(@options, data, @) else - unless selected + if not selected value = if @options.id then @options.id(data) else data.id fieldName = @options.fieldName field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") - selected = true if field.length + if field.length + selected = true # Set URL if @options.url? @@ -410,15 +433,16 @@ class GitLabDropdown else text = if data.text? then data.text else '' - cssClass = '' + cssClass = "" - cssClass = 'is-active' if selected + if selected + cssClass = "is-active" if @highlight text = @highlightTextMatches(text, @filterInput.val()) if group - groupAttrs = "data-group=#{group} data-index=#{index}" + groupAttrs = "data-group='#{group}' data-index='#{index}'" else groupAttrs = '' html = _.template('
          • @@ -432,7 +456,7 @@ class GitLabDropdown text: text }) - html + return html highlightTextMatches: (text, term) -> occurrences = fuzzaldrinPlus.match(text, term) @@ -452,9 +476,9 @@ class GitLabDropdown isInput = $(@el).is('input') if @renderedData - groupName = el.data 'group' + groupName = el.data('group') if groupName - selectedIndex = el.data 'index' + selectedIndex = el.data('index') selectedObject = @renderedData[groupName][selectedIndex] else selectedIndex = el.closest('li').index() @@ -477,19 +501,20 @@ class GitLabDropdown # Toggle the dropdown label if @options.toggleLabel - @updateLabel(selectedObject, el, this) + @updateLabel(selectedObject, el, @) else selectedObject else if el.hasClass(INDETERMINATE_CLASS) el.addClass ACTIVE_CLASS el.removeClass INDETERMINATE_CLASS - field.remove() unless value? + if not value? + field.remove() if not field.length and fieldName @addInput(fieldName, value) - selectedObject + return selectedObject else if not @options.multiSelect or el.hasClass('dropdown-clear-active') @dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS @@ -497,29 +522,30 @@ class GitLabDropdown unless isInput @dropdown.parent().find("input[name='#{fieldName}']").remove() - field.remove() unless value? + if !value? + field.remove() # Toggle active class for the tick mark el.addClass ACTIVE_CLASS # Toggle the dropdown label if @options.toggleLabel - @updateLabel(selectedObject, el, this) + @updateLabel(selectedObject, el, @) if value? - if not field.length and fieldName + if !field.length and fieldName @addInput(fieldName, value) else field .val value .trigger 'change' - selectedObject + return selectedObject addInput: (fieldName, value)-> # Create hidden input for form $input = $('').attr('type', 'hidden') - .attr('name', fieldName) - .val(value) + .attr('name', fieldName) + .val(value) if @options.inputId? $input.attr('id', @options.inputId) @@ -530,21 +556,22 @@ class GitLabDropdown # Dropdown list item link selector, excluding non-selectable list items selector = "#{SELECTABLE_CLASSES}:eq(#{index}) a" - if @dropdown.find('.dropdown-toggle-page').length + if @dropdown.find(".dropdown-toggle-page").length selector = ".dropdown-page-one #{selector}" # simulate a click on the first link $el = $(selector, @dropdown) + if $el.length e.preventDefault() e.stopImmediatePropagation() - $el.first().trigger 'click' + $el.first().trigger('click') href = $el.attr 'href' Turbolinks.visit(href) if href and href isnt '#' addArrowKeyEvent: -> ARROW_KEY_CODES = [38, 40] - $input = @dropdown.find '.dropdown-input-field' + $input = @dropdown.find(".dropdown-input-field") # Dropdown list item selector, excluding non-selectable list items selector = SELECTABLE_CLASSES @@ -571,8 +598,7 @@ class GitLabDropdown # Move up currentIndex -= 1 if currentIndex > 0 - if currentIndex isnt PREV_INDEX - @highlightRowAtIndex($listItems, currentIndex) + @highlightRowAtIndex($listItems, currentIndex) if currentIndex isnt PREV_INDEX return false @@ -596,7 +622,7 @@ class GitLabDropdown # Update the class for the row at the specific index $listItem = $listItems.eq(index) - $listItem.find('a:first-child').addClass 'is-focused' + $listItem.find('a:first-child').addClass "is-focused" # Dropdown content scroll area $dropdownContent = $listItem.closest('.dropdown-content') @@ -624,9 +650,9 @@ class GitLabDropdown $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING) updateLabel: (selected = null, el = null, instance = null) => - $(@el).find('.dropdown-toggle-text').text @options.toggleLabel(selected, el, instance) + $(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selected, el, instance) $.fn.glDropdown = (opts) -> - @each -> - unless $.data this, 'glDropdown' - $.data this, 'glDropdown', new GitLabDropdown this, opts + return @.each -> + if (!$.data @, 'glDropdown') + $.data(@, 'glDropdown', new GitLabDropdown @, opts) diff --git a/app/assets/javascripts/search_autocomplete.js.coffee b/app/assets/javascripts/search_autocomplete.js.coffee index a3baea1ae01..fc74959b1e1 100644 --- a/app/assets/javascripts/search_autocomplete.js.coffee +++ b/app/assets/javascripts/search_autocomplete.js.coffee @@ -315,11 +315,10 @@ class @SearchAutocomplete disableAutocomplete: -> # If not disabled already, disable - if not @searchInput.hasClass('disabled') && @dropdown.hasClass('open') + if not @searchInput.hasClass('disabled') and @dropdown.hasClass 'open' @searchInput.addClass('disabled') # Close dropdown and invoke its hidden() method - @dropdown.removeClass('open') - .trigger('hidden.bs.dropdown') + @dropdown.removeClass('open').trigger 'hidden.bs.dropdown' @restoreMenu() restoreMenu: -> -- cgit v1.2.1 From e74d12a9b3e76c6d49ff1c57bd6471073d34be4a Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Fri, 22 Jul 2016 16:17:43 +0100 Subject: Fix failed tests --- app/assets/javascripts/gl_dropdown.js.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee index 51f739ae201..e0dae228f7a 100644 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ b/app/assets/javascripts/gl_dropdown.js.coffee @@ -442,7 +442,7 @@ class GitLabDropdown text = @highlightTextMatches(text, @filterInput.val()) if group - groupAttrs = "data-group='#{group}' data-index='#{index}'" + groupAttrs = "data-group=#{group} data-index=#{index}" else groupAttrs = '' html = _.template('
          • -- cgit v1.2.1 From dcf09a532b7eff230bf2a646fdb96e9aa43ff189 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Wed, 27 Jul 2016 01:17:07 +0100 Subject: Moved changes across to es5 and changed spec to es6 --- app/assets/javascripts/gl_dropdown.js | 65 +- app/assets/javascripts/gl_dropdown.js.coffee | 658 --------------------- app/assets/javascripts/search_autocomplete.js | 18 +- .../javascripts/search_autocomplete.js.coffee | 348 ----------- 4 files changed, 55 insertions(+), 1034 deletions(-) delete mode 100644 app/assets/javascripts/gl_dropdown.js.coffee delete mode 100644 app/assets/javascripts/search_autocomplete.js.coffee (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index d3394fae3f9..aacc49be1ac 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -191,6 +191,12 @@ currentIndex = -1; + NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link'; + + SELECTABLE_CLASSES = ".dropdown-content li:not(" + NON_SELECTABLE_CLASSES + ")"; + + CURSOR_SELECT_SCROLL_PADDING = 5 + FILTER_INPUT = '.dropdown-input .dropdown-input-field'; function GitLabDropdown(el1, options) { @@ -213,6 +219,7 @@ if (this.options.data) { if (_.isObject(this.options.data) && !_.isFunction(this.options.data)) { this.fullData = this.options.data; + currentIndex = -1 this.parseData(this.options.data); } else { this.remote = new GitLabDropdownRemote(this.options.data, { @@ -240,7 +247,7 @@ keys: searchFields, elements: (function(_this) { return function() { - selector = '.dropdown-content li:not(.divider)'; + selector = SELECTABLE_CLASSES; if (_this.dropdown.find('.dropdown-toggle-page').length) { selector = ".dropdown-page-one " + selector; } @@ -376,7 +383,7 @@ var $target; if (this.options.multiSelect) { $target = $(e.target); - if (!$target.hasClass('dropdown-menu-close') && !$target.hasClass('dropdown-menu-close-icon') && !$target.data('is-link')) { + if ($target && !$target.hasClass('dropdown-menu-close') && !$target.hasClass('dropdown-menu-close-icon') && !$target.data('is-link')) { e.stopPropagation(); return false; } else { @@ -387,7 +394,7 @@ GitLabDropdown.prototype.opened = function() { var contentHtml; - currentIndex = -1; + this.resetRows(); this.addArrowKeyEvent(); if (this.options.setIndeterminateIds) { this.options.setIndeterminateIds.call(this); @@ -410,6 +417,7 @@ GitLabDropdown.prototype.hidden = function(e) { var $input; + this.resetRows(); this.removeArrayKeyEvent(); $input = this.dropdown.find(".dropdown-input-field"); if (this.options.filterable) { @@ -463,7 +471,7 @@ return "
          • "; } if (data.header != null) { - return ""; + return _.template('')({ header: data.header }); } if (this.options.renderRow) { html = this.options.renderRow.call(this.options, data, this); @@ -498,7 +506,12 @@ } else { groupAttrs = ''; } - html = "
          • " + text + "
          • "; + html = _.template('
          • class="<%- cssClass %>"><%= text %>
          • ')({ + url: url, + groupAttrs: groupAttrs, + cssClass: cssClass, + text: text + }); } return html; }; @@ -520,17 +533,6 @@ return html = ""; }; - GitLabDropdown.prototype.highlightRow = function(index) { - var selector; - if (this.filterInput.val() !== "") { - selector = '.dropdown-content li:first-child a'; - if (this.dropdown.find(".dropdown-toggle-page").length) { - selector = ".dropdown-page-one .dropdown-content li:first-child a"; - } - return this.getElement(selector).addClass('is-focused'); - } - }; - GitLabDropdown.prototype.rowClicked = function(el) { var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value; fieldName = this.options.fieldName; @@ -609,13 +611,17 @@ GitLabDropdown.prototype.selectRowAtIndex = function(index) { var $el, selector; - selector = ".dropdown-content li:not(.divider,.dropdown-header,.separator):eq(" + index + ") a"; + selector = SELECTABLE_CLASSES + ":eq(" + index + ") a"; if (this.dropdown.find(".dropdown-toggle-page").length) { selector = ".dropdown-page-one " + selector; } $el = $(selector, this.dropdown); if ($el.length) { - return $el.first().trigger('click'); + e.preventDefault(); + e.stopImmediatePropagation(); + $el.first().trigger('click'); + href = $el.attr('href'); + if (href && href !== '#') Turbolinks.visit(href); } }; @@ -623,7 +629,7 @@ var $input, ARROW_KEY_CODES, selector; ARROW_KEY_CODES = [38, 40]; $input = this.dropdown.find(".dropdown-input-field"); - selector = '.dropdown-content li:not(.divider,.dropdown-header,.separator):visible'; + selector = SELECTABLE_CLASSES; if (this.dropdown.find(".dropdown-toggle-page").length) { selector = ".dropdown-page-one " + selector; } @@ -651,7 +657,9 @@ return false; } if (currentKeyCode === 13 && currentIndex !== -1) { - return _this.selectRowAtIndex($('.is-focused', _this.dropdown).closest('li').index() - 1); + e.preventDefault() + e.stopImmediatePropagation() + return _this.selectRowAtIndex(currentIndex); } }; })(this)); @@ -661,6 +669,11 @@ return $('body').off('keydown'); }; + GitLabDropdown.prototype.resetRows = function resetRows() { + currentIndex = -1; + $('.is-focused', this.dropdown).removeClass('is-focused'); + }; + GitLabDropdown.prototype.highlightRowAtIndex = function($listItems, index) { var $dropdownContent, $listItem, dropdownContentBottom, dropdownContentHeight, dropdownContentTop, dropdownScrollTop, listItemBottom, listItemHeight, listItemTop; $('.is-focused', this.dropdown).removeClass('is-focused'); @@ -674,10 +687,14 @@ listItemHeight = $listItem.outerHeight(); listItemTop = $listItem.prop('offsetTop'); listItemBottom = listItemTop + listItemHeight; - if (listItemBottom > dropdownContentBottom + dropdownScrollTop) { - return $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom); - } else if (listItemTop < dropdownContentTop + dropdownScrollTop) { - return $dropdownContent.scrollTop(listItemTop - dropdownContentTop); + if (!index) { + $dropdownContent.scrollTop(0) + } else if (index === ($listItems.length - 1)) { + $dropdownContent.scrollTop $dropdownContent.prop('scrollHeight'); + } else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) + $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING); + } else if (listItemTop < (dropdownContentTop + dropdownScrollTop)) { + return $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING); } }; diff --git a/app/assets/javascripts/gl_dropdown.js.coffee b/app/assets/javascripts/gl_dropdown.js.coffee deleted file mode 100644 index e0dae228f7a..00000000000 --- a/app/assets/javascripts/gl_dropdown.js.coffee +++ /dev/null @@ -1,658 +0,0 @@ -class GitLabDropdownFilter - BLUR_KEYCODES = [27, 40] - ARROW_KEY_CODES = [38, 40] - HAS_VALUE_CLASS = "has-value" - - constructor: (@input, @options) -> - { - @filterInputBlur = true - } = @options - - $inputContainer = @input.parent() - $clearButton = $inputContainer.find('.js-dropdown-input-clear') - - @indeterminateIds = [] - - # Clear click - $clearButton.on 'click', (e) => - e.preventDefault() - e.stopPropagation() - @input - .val('') - .trigger('keyup') - .focus() - - # Key events - timeout = "" - @input.on "keyup", (e) => - keyCode = e.which - - return if ARROW_KEY_CODES.indexOf(keyCode) >= 0 - - if @input.val() isnt "" and !$inputContainer.hasClass HAS_VALUE_CLASS - $inputContainer.addClass HAS_VALUE_CLASS - else if @input.val() is "" and $inputContainer.hasClass HAS_VALUE_CLASS - $inputContainer.removeClass HAS_VALUE_CLASS - - if keyCode is 13 - return false - - # Only filter asynchronously only if option remote is set - if @options.remote - clearTimeout timeout - timeout = setTimeout => - blur_field = @shouldBlur keyCode - - if blur_field and @filterInputBlur - @input.blur() - - @options.query @input.val(), (data) => - @options.callback(data) - , 250 - else - @filter @input.val() - - shouldBlur: (keyCode) -> - return BLUR_KEYCODES.indexOf(keyCode) >= 0 - - filter: (search_text) -> - @options.onFilter(search_text) if @options.onFilter - data = @options.data() - - if data? and not @options.filterByText - results = data - - if search_text isnt '' - # When data is an array of objects therefore [object Array] e.g. - # [ - # { prop: 'foo' }, - # { prop: 'baz' } - # ] - if _.isArray(data) - results = fuzzaldrinPlus.filter(data, search_text, - key: @options.keys - ) - else - # If data is grouped therefore an [object Object]. e.g. - # { - # groupName1: [ - # { prop: 'foo' }, - # { prop: 'baz' } - # ], - # groupName2: [ - # { prop: 'abc' }, - # { prop: 'def' } - # ] - # } - if gl.utils.isObject data - results = {} - for key, group of data - tmp = fuzzaldrinPlus.filter(group, search_text, - key: @options.keys - ) - - if tmp.length - results[key] = tmp.map (item) -> item - - @options.callback results - else - elements = @options.elements() - - if search_text - elements.each -> - $el = $(@) - matches = fuzzaldrinPlus.match($el.text().trim(), search_text) - - unless $el.is('.dropdown-header') - if matches.length - $el.show() - else - $el.hide() - else - elements.show() - -class GitLabDropdownRemote - constructor: (@dataEndpoint, @options) -> - - execute: -> - if typeof @dataEndpoint is "string" - @fetchData() - else if typeof @dataEndpoint is "function" - if @options.beforeSend - @options.beforeSend() - - # Fetch the data by calling the data funcfion - @dataEndpoint "", (data) => - if @options.success - @options.success(data) - if @options.beforeSend - @options.beforeSend() - - # Fetch the data through ajax if the data is a string - fetchData: -> - $.ajax( - url: @dataEndpoint, - dataType: @options.dataType, - beforeSend: => - if @options.beforeSend - @options.beforeSend() - success: (data) => - if @options.success - @options.success(data) - ) - -class GitLabDropdown - LOADING_CLASS = "is-loading" - PAGE_TWO_CLASS = "is-page-two" - ACTIVE_CLASS = "is-active" - INDETERMINATE_CLASS = "is-indeterminate" - currentIndex = -1 - NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link' - SELECTABLE_CLASSES = ".dropdown-content li:not(#{NON_SELECTABLE_CLASSES})" - FILTER_INPUT = '.dropdown-input .dropdown-input-field' - CURSOR_SELECT_SCROLL_PADDING = 5 - - constructor: (@el, @options) -> - self = @ - selector = $(@el).data "target" - @dropdown = if selector? then $(selector) else $(@el).parent() - - # Set Defaults - { - # If no input is passed create a default one - @filterInput = @getElement(FILTER_INPUT) - @highlight = false - @filterInputBlur = true - } = @options - - self = @ - - # If selector was passed - if _.isString(@filterInput) - @filterInput = @getElement(@filterInput) - - searchFields = if @options.search then @options.search.fields else [] - - if @options.data - # If we provided data - # data could be an array of objects or a group of arrays - if _.isObject(@options.data) and not _.isFunction(@options.data) - @fullData = @options.data - @parseData @options.data - else - # Remote data - @remote = new GitLabDropdownRemote @options.data, { - dataType: @options.dataType, - beforeSend: @toggleLoading.bind(@) - success: (data) => - @fullData = data - - # Reset selected row index on new data - currentIndex = -1 - @parseData @fullData - - @filter.input.trigger('keyup') if @options.filterable and @filter and @filter.input - } - - # Init filterable - if @options.filterable - @filter = new GitLabDropdownFilter @filterInput, - filterInputBlur: @filterInputBlur - filterByText: @options.filterByText - onFilter: @options.onFilter - remote: @options.filterRemote - query: @options.data - keys: searchFields - elements: => - selector = SELECTABLE_CLASSES - - if @dropdown.find('.dropdown-toggle-page').length - selector = ".dropdown-page-one #{selector}" - - return $(selector) - data: => - return @fullData - callback: (data) => - @parseData data - - unless @filterInput.val() is '' - selector = '.dropdown-content li:not(.divider):visible' - - if @dropdown.find('.dropdown-toggle-page').length - selector = ".dropdown-page-one #{selector}" - - $(selector, @dropdown) - .first() - .find('a') - .addClass('is-focused') - - currentIndex = 0 - - - # Event listeners - - @dropdown.on "shown.bs.dropdown", @opened - @dropdown.on "hidden.bs.dropdown", @hidden - $(@el).on "update.label", @updateLabel - @dropdown.on "click", ".dropdown-menu, .dropdown-menu-close", @shouldPropagate - @dropdown.on 'keyup', (e) => - if e.which is 27 # Escape key - $('.dropdown-menu-close', @dropdown).trigger 'click' - - @dropdown.on 'blur', 'a', (e) => - if e.relatedTarget? - $relatedTarget = $(e.relatedTarget) - $dropdownMenu = $relatedTarget.closest('.dropdown-menu') - - if $dropdownMenu.length is 0 - @dropdown.removeClass('open') - - if @dropdown.find(".dropdown-toggle-page").length - @dropdown.find(".dropdown-toggle-page, .dropdown-menu-back").on "click", (e) => - e.preventDefault() - e.stopPropagation() - - @togglePage() - - if @options.selectable - selector = ".dropdown-content a" - - if @dropdown.find(".dropdown-toggle-page").length - selector = ".dropdown-page-one .dropdown-content a" - - @dropdown.on "click", selector, (e) -> - $el = $(@) - selected = self.rowClicked $el - - if self.options.clicked - self.options.clicked(selected, $el, e) - - $el.trigger('blur') - - # Finds an element inside wrapper element - getElement: (selector) -> - @dropdown.find selector - - toggleLoading: -> - $('.dropdown-menu', @dropdown).toggleClass LOADING_CLASS - - togglePage: -> - menu = $('.dropdown-menu', @dropdown) - - if menu.hasClass(PAGE_TWO_CLASS) - if @remote - @remote.execute() - - menu.toggleClass PAGE_TWO_CLASS - - # Focus first visible input on active page - @dropdown.find('[class^="dropdown-page-"]:visible :text:visible:first').focus() - - parseData: (data) -> - @renderedData = data - - if @options.filterable and data.length is 0 - # render no matching results - html = [@noResults()] - else - # Handle array groups - if gl.utils.isObject data - html = [] - for name, groupData of data - # Add header for each group - html.push(@renderItem(header: name, name)) - - @renderData(groupData, name) - .map (item) -> - html.push item - else - # Render each row - html = @renderData(data) - - # Render the full menu - full_html = @renderMenu(html) - - @appendMenu(full_html) - - renderData: (data, group = false) -> - data.map (obj, index) => - return @renderItem(obj, group, index) - - shouldPropagate: (e) => - if @options.multiSelect - $target = $(e.target) - - if $target and not $target.hasClass('dropdown-menu-close') and not $target.hasClass('dropdown-menu-close-icon') and not $target.data('is-link') - e.stopPropagation() - return false - else - return true - - opened: => - @resetRows() - @addArrowKeyEvent() - - if @options.setIndeterminateIds - @options.setIndeterminateIds.call(@) - - if @options.setActiveIds - @options.setActiveIds.call(@) - - # Makes indeterminate items effective - if @fullData and @dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update') - @parseData @fullData - - contentHtml = $('.dropdown-content', @dropdown).html() - if @remote && contentHtml is "" - @remote.execute() - - if @options.filterable - @filterInput.focus() - - @dropdown.trigger('shown.gl.dropdown') - - hidden: (e) => - @resetRows() - @removeArrayKeyEvent() - - $input = @dropdown.find(".dropdown-input-field") - - if @options.filterable - $input - .blur() - .val("") - - # Triggering 'keyup' will re-render the dropdown which is not always required - # specially if we want to keep the state of the dropdown needed for bulk-assignment - if not @options.persistWhenHide - $input.trigger("keyup") - - if @dropdown.find(".dropdown-toggle-page").length - $('.dropdown-menu', @dropdown).removeClass PAGE_TWO_CLASS - - if @options.hidden - @options.hidden.call(@,e) - - @dropdown.trigger('hidden.gl.dropdown') - - - # Render the full menu - renderMenu: (html) -> - menu_html = "" - - if @options.renderMenu - menu_html = @options.renderMenu(html) - else - menu_html = $('
              ') - .append(html) - - return menu_html - - # Append the menu into the dropdown - appendMenu: (html) -> - selector = '.dropdown-content' - if @dropdown.find(".dropdown-toggle-page").length - selector = ".dropdown-page-one .dropdown-content" - $(selector, @dropdown) - .empty() - .append(html) - - # Render the row - renderItem: (data, group = false, index = false) -> - html = "" - - # Divider - return '
            • ' if data is 'divider' - - # Separator is a full-width divider - return '
            • ' if data is 'separator' - - # Header - return _.template('')({ header: data.header }) if data.header? - - if @options.renderRow - # Call the render function - html = @options.renderRow.call(@options, data, @) - else - if not selected - value = if @options.id then @options.id(data) else data.id - fieldName = @options.fieldName - field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") - if field.length - selected = true - - # Set URL - if @options.url? - url = @options.url(data) - else - url = if data.url? then data.url else '#' - - # Set Text - if @options.text? - text = @options.text(data) - else - text = if data.text? then data.text else '' - - cssClass = "" - - if selected - cssClass = "is-active" - - if @highlight - text = @highlightTextMatches(text, @filterInput.val()) - - if group - groupAttrs = "data-group=#{group} data-index=#{index}" - else - groupAttrs = '' - html = _.template('
            • - class="<%- cssClass %>"> - <%= text %> - -
            • ')({ - url: url - groupAttrs: groupAttrs - cssClass: cssClass - text: text - }) - - return html - - highlightTextMatches: (text, term) -> - occurrences = fuzzaldrinPlus.match(text, term) - text.split('').map((character, i) -> - if i in occurrences then "#{character}" else character - ).join('') - - noResults: -> - html = '' - - rowClicked: (el) -> - fieldName = @options.fieldName - isInput = $(@el).is('input') - - if @renderedData - groupName = el.data('group') - if groupName - selectedIndex = el.data('index') - selectedObject = @renderedData[groupName][selectedIndex] - else - selectedIndex = el.closest('li').index() - selectedObject = @renderedData[selectedIndex] - - value = if @options.id then @options.id(selectedObject, el) else selectedObject.id - - if isInput - field = $(@el) - else - field = @dropdown.parent().find("input[name='#{fieldName}'][value='#{value}']") - - if el.hasClass(ACTIVE_CLASS) - el.removeClass(ACTIVE_CLASS) - - if isInput - field.val('') - else - field.remove() - - # Toggle the dropdown label - if @options.toggleLabel - @updateLabel(selectedObject, el, @) - else - selectedObject - else if el.hasClass(INDETERMINATE_CLASS) - el.addClass ACTIVE_CLASS - el.removeClass INDETERMINATE_CLASS - - if not value? - field.remove() - - if not field.length and fieldName - @addInput(fieldName, value) - - return selectedObject - else - if not @options.multiSelect or el.hasClass('dropdown-clear-active') - @dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS - - unless isInput - @dropdown.parent().find("input[name='#{fieldName}']").remove() - - if !value? - field.remove() - - # Toggle active class for the tick mark - el.addClass ACTIVE_CLASS - - # Toggle the dropdown label - if @options.toggleLabel - @updateLabel(selectedObject, el, @) - if value? - if !field.length and fieldName - @addInput(fieldName, value) - else - field - .val value - .trigger 'change' - - return selectedObject - - addInput: (fieldName, value)-> - # Create hidden input for form - $input = $('').attr('type', 'hidden') - .attr('name', fieldName) - .val(value) - - if @options.inputId? - $input.attr('id', @options.inputId) - - @dropdown.before $input - - selectRowAtIndex: (e, index) -> - # Dropdown list item link selector, excluding non-selectable list items - selector = "#{SELECTABLE_CLASSES}:eq(#{index}) a" - - if @dropdown.find(".dropdown-toggle-page").length - selector = ".dropdown-page-one #{selector}" - - # simulate a click on the first link - $el = $(selector, @dropdown) - - if $el.length - e.preventDefault() - e.stopImmediatePropagation() - $el.first().trigger('click') - href = $el.attr 'href' - Turbolinks.visit(href) if href and href isnt '#' - - addArrowKeyEvent: -> - ARROW_KEY_CODES = [38, 40] - $input = @dropdown.find(".dropdown-input-field") - - # Dropdown list item selector, excluding non-selectable list items - selector = SELECTABLE_CLASSES - if @dropdown.find('.dropdown-toggle-page').length - selector = ".dropdown-page-one #{selector}" - - $('body').on 'keydown', (e) => - currentKeyCode = e.which - - if ARROW_KEY_CODES.indexOf(currentKeyCode) >= 0 - e.preventDefault() - e.stopImmediatePropagation() - - PREV_INDEX = currentIndex - $listItems = $(selector, @dropdown) - - # if @options.filterable - # $input.blur() - - if currentKeyCode is 40 - # Move down - currentIndex += 1 if currentIndex < ($listItems.length - 1) - else if currentKeyCode is 38 - # Move up - currentIndex -= 1 if currentIndex > 0 - - @highlightRowAtIndex($listItems, currentIndex) if currentIndex isnt PREV_INDEX - - return false - - # If enter is pressed and a row is highlighted, select it - if currentKeyCode is 13 and currentIndex isnt -1 - e.preventDefault() - e.stopImmediatePropagation() - @selectRowAtIndex e, currentIndex - - removeArrayKeyEvent: -> - $('body').off 'keydown' - - # Resets the currently selected item row index and removes all highlights - resetRows: -> - currentIndex = -1 - $('.is-focused', @dropdown).removeClass 'is-focused' - - highlightRowAtIndex: ($listItems, index) -> - # Remove the class for the previously focused row - $('.is-focused', @dropdown).removeClass 'is-focused' - - # Update the class for the row at the specific index - $listItem = $listItems.eq(index) - $listItem.find('a:first-child').addClass "is-focused" - - # Dropdown content scroll area - $dropdownContent = $listItem.closest('.dropdown-content') - dropdownScrollTop = $dropdownContent.scrollTop() - dropdownContentHeight = $dropdownContent.outerHeight() - dropdownContentTop = $dropdownContent.prop('offsetTop') - dropdownContentBottom = dropdownContentTop + dropdownContentHeight - - # Get the offset bottom of the list item - listItemHeight = $listItem.outerHeight() - listItemTop = $listItem.prop('offsetTop') - listItemBottom = listItemTop + listItemHeight - - if index is 0 - # If this is the first item in the list, scroll to the top - $dropdownContent.scrollTop(0) - else if index is $listItems.length - 1 - # If this is the last item in the list, scroll to the bottom - $dropdownContent.scrollTop $dropdownContent.prop 'scrollHeight' - else if listItemBottom > dropdownContentBottom + dropdownScrollTop - # Scroll the dropdown content down with a little padding - $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING) - else if listItemTop < dropdownContentTop + dropdownScrollTop - # Scroll the dropdown content up with a little padding - $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING) - - updateLabel: (selected = null, el = null, instance = null) => - $(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selected, el, instance) - -$.fn.glDropdown = (opts) -> - return @.each -> - if (!$.data @, 'glDropdown') - $.data(@, 'glDropdown', new GitLabDropdown @, opts) diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index 990f6536eb2..cd39f5f94e2 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -7,7 +7,9 @@ KEYCODE = { ESCAPE: 27, BACKSPACE: 8, - ENTER: 13 + ENTER: 13, + UP: 38, + DOWN: 40 }; function SearchAutocomplete(opts) { @@ -223,6 +225,12 @@ case KEYCODE.ESCAPE: this.restoreOriginalState(); break; + case KEYCODE.ENTER: + this.disableAutocomplete(); + break; + case KEYCODE.UP, + case KEYCODE.DOWN: + return; default: if (this.searchInput.val() === '') { this.disableAutocomplete(); @@ -319,9 +327,11 @@ }; SearchAutocomplete.prototype.disableAutocomplete = function() { - this.searchInput.addClass('disabled'); - this.dropdown.removeClass('open'); - return this.restoreMenu(); + if (!this.searchInput.hasClass('disabled') && this.dropdown.hasClass('open')) { + this.searchInput.addClass('disabled'); + this.dropdown.removeClass('open').trigger('hidden.bs.dropdown'); + this.restoreMenu(); + } }; SearchAutocomplete.prototype.restoreMenu = function() { diff --git a/app/assets/javascripts/search_autocomplete.js.coffee b/app/assets/javascripts/search_autocomplete.js.coffee deleted file mode 100644 index fc74959b1e1..00000000000 --- a/app/assets/javascripts/search_autocomplete.js.coffee +++ /dev/null @@ -1,348 +0,0 @@ -class @SearchAutocomplete - - KEYCODE = - ESCAPE: 27 - BACKSPACE: 8 - ENTER: 13 - UP: 38 - DOWN: 40 - - constructor: (opts = {}) -> - { - @wrap = $('.search') - - @optsEl = @wrap.find('.search-autocomplete-opts') - @autocompletePath = @optsEl.data('autocomplete-path') - @projectId = @optsEl.data('autocomplete-project-id') || '' - @projectRef = @optsEl.data('autocomplete-project-ref') || '' - - } = opts - - # Dropdown Element - @dropdown = @wrap.find('.dropdown') - @dropdownContent = @dropdown.find('.dropdown-content') - - @locationBadgeEl = @getElement('.location-badge') - @scopeInputEl = @getElement('#scope') - @searchInput = @getElement('.search-input') - @projectInputEl = @getElement('#search_project_id') - @groupInputEl = @getElement('#group_id') - @searchCodeInputEl = @getElement('#search_code') - @repositoryInputEl = @getElement('#repository_ref') - @clearInput = @getElement('.js-clear-input') - - @saveOriginalState() - - # Only when user is logged in - @createAutocomplete() if gon.current_user_id - - @searchInput.addClass('disabled') - - @saveTextLength() - - @bindEvents() - - # Finds an element inside wrapper element - getElement: (selector) -> - @wrap.find(selector) - - saveOriginalState: -> - @originalState = @serializeState() - - saveTextLength: -> - @lastTextLength = @searchInput.val().length - - createAutocomplete: -> - @searchInput.glDropdown - filterInputBlur: false - filterable: true - filterRemote: true - highlight: true - enterCallback: false - filterInput: 'input#search' - search: - fields: ['text'] - data: @getData.bind(@) - selectable: true - clicked: @onClick.bind(@) - - getData: (term, callback) -> - _this = @ - - unless term - if contents = @getCategoryContents() - @searchInput.data('glDropdown').filter.options.callback contents - @enableAutocomplete() - - return - - # Prevent multiple ajax calls - return if @loadingSuggestions - - @loadingSuggestions = true - - jqXHR = $.get(@autocompletePath, { - project_id: @projectId - project_ref: @projectRef - term: term - }, (response) -> - # Hide dropdown menu if no suggestions returns - if !response.length - _this.disableAutocomplete() - return - - data = [] - - # List results - firstCategory = true - for suggestion in response - - # Add group header before list each group - if lastCategory isnt suggestion.category - data.push 'separator' if !firstCategory - - firstCategory = false if firstCategory - - data.push - header: suggestion.category - - lastCategory = suggestion.category - - data.push - id: "#{suggestion.category.toLowerCase()}-#{suggestion.id}" - category: suggestion.category - text: suggestion.label - url: suggestion.url - - # Add option to proceed with the search - if data.length - data.push('separator') - data.push - text: "Result name contains \"#{term}\"" - url: "/search?\ - search=#{term}\ - &project_id=#{_this.projectInputEl.val()}\ - &group_id=#{_this.groupInputEl.val()}" - - callback(data) - ).always -> - _this.loadingSuggestions = false - - - getCategoryContents: -> - - userId = gon.current_user_id - { utils, projectOptions, groupOptions, dashboardOptions } = gl - - if utils.isInGroupsPage() and groupOptions - options = groupOptions[utils.getGroupSlug()] - - else if utils.isInProjectPage() and projectOptions - options = projectOptions[utils.getProjectSlug()] - - else if dashboardOptions - options = dashboardOptions - - { issuesPath, mrPath, name } = options - - items = [ - { header: "#{name}" } - { text: 'Issues assigned to me', url: "#{issuesPath}/?assignee_id=#{userId}" } - { text: "Issues I've created", url: "#{issuesPath}/?author_id=#{userId}" } - 'separator' - { text: 'Merge requests assigned to me', url: "#{mrPath}/?assignee_id=#{userId}" } - { text: "Merge requests I've created", url: "#{mrPath}/?author_id=#{userId}" } - ] - - items.splice 0, 1 unless name - - return items - - - serializeState: -> - { - # Search Criteria - search_project_id: @projectInputEl.val() - group_id: @groupInputEl.val() - search_code: @searchCodeInputEl.val() - repository_ref: @repositoryInputEl.val() - scope: @scopeInputEl.val() - - # Location badge - _location: @locationBadgeEl.text() - } - - bindEvents: -> - @searchInput.on 'keydown', @onSearchInputKeyDown - @searchInput.on 'keyup', @onSearchInputKeyUp - @searchInput.on 'click', @onSearchInputClick - @searchInput.on 'focus', @onSearchInputFocus - @searchInput.on 'blur', @onSearchInputBlur - @clearInput.on 'click', @onClearInputClick - @locationBadgeEl.on 'click', => - @searchInput.focus() - - enableAutocomplete: -> - # No need to enable anything if user is not logged in - return if !gon.current_user_id - - unless @dropdown.hasClass('open') - _this = @ - @loadingSuggestions = false - - # If not enabled already, enable - if not @dropdown.hasClass('open') - # Open dropdown and invoke its opened() method - @dropdown.addClass('open') - .trigger('shown.bs.dropdown') - @searchInput.removeClass('disabled') - - onSearchInputKeyDown: => - # Saves last length of the entered text - @saveTextLength() - - onSearchInputKeyUp: (e) => - switch e.keyCode - when KEYCODE.BACKSPACE - # when trying to remove the location badge - if @lastTextLength is 0 and @badgePresent() - @removeLocationBadge() - - # When removing the last character and no badge is present - if @lastTextLength is 1 - @disableAutocomplete() - - # When removing any character from existin value - if @lastTextLength > 1 - @enableAutocomplete() - - when KEYCODE.ESCAPE - @restoreOriginalState() - - # Close autocomplete on enter - when KEYCODE.ENTER - @disableAutocomplete() - - when KEYCODE.UP, KEYCODE.DOWN - return - - else - # Handle the case when deleting the input value other than backspace - # e.g. Pressing ctrl + backspace or ctrl + x - if @searchInput.val() is '' - @disableAutocomplete() - else - # We should display the menu only when input is not empty - @enableAutocomplete() - - @wrap.toggleClass 'has-value', !!e.target.value - - # Avoid falsy value to be returned - return - - onSearchInputClick: (e) => - # Prevents closing the dropdown menu - e.stopImmediatePropagation() - - onSearchInputFocus: => - @isFocused = true - @wrap.addClass('search-active') - - @getData() if @getValue() is '' - - - getValue: -> return @searchInput.val() - - - onClearInputClick: (e) => - e.preventDefault() - @searchInput.val('').focus() - - onSearchInputBlur: (e) => - @isFocused = false - @wrap.removeClass('search-active') - - # If input is blank then restore state - if @searchInput.val() is '' - @restoreOriginalState() - - addLocationBadge: (item) -> - category = if item.category? then "#{item.category}: " else '' - value = if item.value? then item.value else '' - - badgeText = "#{category}#{value}" - @locationBadgeEl.text(badgeText).show() - @wrap.addClass('has-location-badge') - - - hasLocationBadge: -> return @wrap.is '.has-location-badge' - - - restoreOriginalState: -> - inputs = Object.keys @originalState - - for input in inputs - @getElement("##{input}").val(@originalState[input]) - - if @originalState._location is '' - @locationBadgeEl.hide() - else - @addLocationBadge( - value: @originalState._location - ) - - badgePresent: -> - @locationBadgeEl.length - - resetSearchState: -> - inputs = Object.keys @originalState - - for input in inputs - - # _location isnt a input - break if input is '_location' - - @getElement("##{input}").val('') - - - removeLocationBadge: -> - - @locationBadgeEl.hide() - @resetSearchState() - @wrap.removeClass('has-location-badge') - @disableAutocomplete() - - - disableAutocomplete: -> - # If not disabled already, disable - if not @searchInput.hasClass('disabled') and @dropdown.hasClass 'open' - @searchInput.addClass('disabled') - # Close dropdown and invoke its hidden() method - @dropdown.removeClass('open').trigger 'hidden.bs.dropdown' - @restoreMenu() - - restoreMenu: -> - html = "" - @dropdownContent.html(html) - - onClick: (item, $el, e) -> - if location.pathname.indexOf(item.url) isnt -1 - e.preventDefault() - if not @badgePresent - if item.category is 'Projects' - @projectInputEl.val(item.id) - @addLocationBadge( - value: 'This project' - ) - - if item.category is 'Groups' - @groupInputEl.val(item.id) - @addLocationBadge( - value: 'This group' - ) - - $el.removeClass('is-active') - @disableAutocomplete() - @searchInput.val('').focus() -- cgit v1.2.1 From 49c7ca2a27639809dd84975d7595787ab5f60647 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Thu, 28 Jul 2016 17:32:43 +0100 Subject: Fixed spec and improved formatting --- app/assets/javascripts/gl_dropdown.js | 4 ++-- app/assets/javascripts/search_autocomplete.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index aacc49be1ac..58e27acf2f1 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -690,8 +690,8 @@ if (!index) { $dropdownContent.scrollTop(0) } else if (index === ($listItems.length - 1)) { - $dropdownContent.scrollTop $dropdownContent.prop('scrollHeight'); - } else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) + $dropdownContent.scrollTop($dropdownContent.prop('scrollHeight')); + } else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) { $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING); } else if (listItemTop < (dropdownContentTop + dropdownScrollTop)) { return $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING); diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index cd39f5f94e2..4579214bd2f 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -228,7 +228,7 @@ case KEYCODE.ENTER: this.disableAutocomplete(); break; - case KEYCODE.UP, + case KEYCODE.UP: case KEYCODE.DOWN: return; default: -- cgit v1.2.1 From 3e1e9b670fdb12159e31664c3757df6696db90e1 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Thu, 28 Jul 2016 23:46:41 +0100 Subject: Fixed specs --- app/assets/javascripts/gl_dropdown.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 58e27acf2f1..7f7f76224c4 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -617,6 +617,7 @@ } $el = $(selector, this.dropdown); if ($el.length) { + return $el.first().trigger('click'); e.preventDefault(); e.stopImmediatePropagation(); $el.first().trigger('click'); @@ -690,8 +691,8 @@ if (!index) { $dropdownContent.scrollTop(0) } else if (index === ($listItems.length - 1)) { - $dropdownContent.scrollTop($dropdownContent.prop('scrollHeight')); - } else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) { + $dropdownContent.scrollTop $dropdownContent.prop('scrollHeight'); + } else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING); } else if (listItemTop < (dropdownContentTop + dropdownScrollTop)) { return $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING); -- cgit v1.2.1 From 2f8fada6c06d7ed67307119bf22e9743429c18be Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Thu, 11 Aug 2016 15:10:23 +0100 Subject: Fixed conflicts --- app/assets/javascripts/gl_dropdown.js | 27 ++++++++++++--------------- app/assets/javascripts/search_autocomplete.js | 2 +- 2 files changed, 13 insertions(+), 16 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 7f7f76224c4..bbda6387c77 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -111,9 +111,9 @@ matches = fuzzaldrinPlus.match($el.text().trim(), search_text); if (!$el.is('.dropdown-header')) { if (matches.length) { - return $el.show(); + return $el.show().removeClass('option-hidden'); } else { - return $el.hide(); + return $el.hide().addClass('option-hidden'); } } }); @@ -191,9 +191,9 @@ currentIndex = -1; - NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link'; + NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link, .option-hidden'; - SELECTABLE_CLASSES = ".dropdown-content li:not(" + NON_SELECTABLE_CLASSES + ")"; + SELECTABLE_CLASSES = ".dropdown-content li:not(" + NON_SELECTABLE_CLASSES + ")"; CURSOR_SELECT_SCROLL_PADDING = 5 @@ -247,7 +247,7 @@ keys: searchFields, elements: (function(_this) { return function() { - selector = SELECTABLE_CLASSES; + selector = '.dropdown-content li:not(' + NON_SELECTABLE_CLASSES + ')'; if (_this.dropdown.find('.dropdown-toggle-page').length) { selector = ".dropdown-page-one " + selector; } @@ -263,7 +263,7 @@ return function(data) { _this.parseData(data); if (_this.filterInput.val() !== '') { - selector = '.dropdown-content li:not(.divider):visible'; + selector = SELECTABLE_CLASSES; if (_this.dropdown.find('.dropdown-toggle-page').length) { selector = ".dropdown-page-one " + selector; } @@ -502,7 +502,7 @@ text = this.highlightTextMatches(text, this.filterInput.val()); } if (group) { - groupAttrs = "data-group='" + group + "' data-index='" + index + "'"; + groupAttrs = 'data-group=' + group + ' data-index=' + index; } else { groupAttrs = ''; } @@ -617,11 +617,8 @@ } $el = $(selector, this.dropdown); if ($el.length) { - return $el.first().trigger('click'); - e.preventDefault(); - e.stopImmediatePropagation(); $el.first().trigger('click'); - href = $el.attr('href'); + var href = $el.attr('href'); if (href && href !== '#') Turbolinks.visit(href); } }; @@ -671,8 +668,8 @@ }; GitLabDropdown.prototype.resetRows = function resetRows() { - currentIndex = -1; - $('.is-focused', this.dropdown).removeClass('is-focused'); + currentIndex = -1; + $('.is-focused', this.dropdown).removeClass('is-focused'); }; GitLabDropdown.prototype.highlightRowAtIndex = function($listItems, index) { @@ -691,8 +688,8 @@ if (!index) { $dropdownContent.scrollTop(0) } else if (index === ($listItems.length - 1)) { - $dropdownContent.scrollTop $dropdownContent.prop('scrollHeight'); - } else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) + $dropdownContent.scrollTop($dropdownContent.prop('scrollHeight')); + } else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) { $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING); } else if (listItemTop < (dropdownContentTop + dropdownScrollTop)) { return $dropdownContent.scrollTop(listItemTop - dropdownContentTop - CURSOR_SELECT_SCROLL_PADDING); diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index 4579214bd2f..37451d406ec 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -9,7 +9,7 @@ BACKSPACE: 8, ENTER: 13, UP: 38, - DOWN: 40 + DOWN: 40 }; function SearchAutocomplete(opts) { -- cgit v1.2.1 From 8086526cf013c4630402db2be47de9020223018c Mon Sep 17 00:00:00 2001 From: winniehell Date: Fri, 19 Aug 2016 10:39:47 +0200 Subject: Fix alignment of icon buttons (!5887) --- app/assets/stylesheets/framework/buttons.scss | 4 +++- app/views/projects/buttons/_fork.html.haml | 4 ++-- app/views/projects/forks/index.html.haml | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 6c3786b49bb..716e79a2354 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -206,7 +206,9 @@ } svg, .fa { - margin-right: 3px; + &:not(:last-child) { + margin-right: 3px; + } } } diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml index d78888e9fe4..22db33498f1 100644 --- a/app/views/projects/buttons/_fork.html.haml +++ b/app/views/projects/buttons/_fork.html.haml @@ -3,11 +3,11 @@ - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn has-tooltip' do = custom_icon('icon_fork') - Fork + %span Fork - else = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn has-tooltip' do = custom_icon('icon_fork') - Fork + %span Fork %div.count-with-arrow %span.arrow = link_to namespace_project_forks_path(@project.namespace, @project), class: "count" do diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml index a1d79bdabda..bacc5708e4b 100644 --- a/app/views/projects/forks/index.html.haml +++ b/app/views/projects/forks/index.html.haml @@ -32,11 +32,11 @@ - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do = custom_icon('icon_fork') - Fork + %span Fork - else = link_to new_namespace_project_fork_path(@project.namespace, @project), title: "Fork project", class: 'btn btn-new' do = custom_icon('icon_fork') - Fork + %span Fork = render 'projects', projects: @forks -- cgit v1.2.1 From e067e699c3250882ea08594243b6c6d3ad84d6e0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Fri, 19 Aug 2016 12:35:16 +0300 Subject: Make sure merge request is fetched before collecting base sha in merge request diff Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index a769d31ac93..42ab6b620bd 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -41,6 +41,7 @@ class MergeRequestDiff < ActiveRecord::Base end def ensure_commits_sha + merge_request.fetch_ref self.start_commit_sha ||= merge_request.target_branch_sha self.head_commit_sha ||= merge_request.source_branch_sha self.base_commit_sha ||= find_base_sha -- cgit v1.2.1 From 1aba3a5c0e7c2b727f4317aab19bbc662f0fd727 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 19 Aug 2016 17:42:49 +0800 Subject: Unify pipeline_for(ref, nil) and pipeline_for(ref), feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_14073464 --- app/models/project.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 678fca7afd1..e97e6abfef9 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1094,8 +1094,11 @@ class Project < ActiveRecord::Base !namespace.share_with_group_lock end - def pipeline_for(ref, sha = commit(ref).try(:sha)) + def pipeline_for(ref, sha = nil) + sha ||= commit(ref).try(:sha) + return unless sha + pipelines.order(id: :desc).find_by(sha: sha, ref: ref) end -- cgit v1.2.1 From cbcf00e1b972265713bb68cc679216398a44c993 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 19 Aug 2016 12:12:50 +0100 Subject: Keep committing ... spinner when conflict resolved When a conflict is resolved, we don't want to change the spinner back to the normal button before the new page load happens, so only do this on failure. --- app/assets/javascripts/merge_conflict_resolver.js.es6 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/merge_conflict_resolver.js.es6 b/app/assets/javascripts/merge_conflict_resolver.js.es6 index 77bffbcb403..b56fd5aa658 100644 --- a/app/assets/javascripts/merge_conflict_resolver.js.es6 +++ b/app/assets/javascripts/merge_conflict_resolver.js.es6 @@ -75,10 +75,8 @@ class MergeConflictResolver { window.location.href = data.redirect_to; }) .error(() => { - new Flash('Something went wrong!'); - }) - .always(() => { this.vue.isSubmitting = false; + new Flash('Something went wrong!'); }); } -- cgit v1.2.1 From 8ade8258603586560fad50784c23e4772706973f Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Fri, 19 Aug 2016 17:17:17 +0100 Subject: review changes --- app/assets/javascripts/gl_dropdown.js | 15 ++++++--------- app/assets/javascripts/search_autocomplete.js | 6 +++--- 2 files changed, 9 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index bbda6387c77..f85aa6dd7b7 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -31,9 +31,8 @@ this.input .on('keydown', function (e) { var keyCode = e.which; - if (keyCode === 13) { - e.preventDefault() + e.preventDefault(); } }) .on('keyup', function(e) { @@ -179,7 +178,7 @@ })(); GitLabDropdown = (function() { - var ACTIVE_CLASS, FILTER_INPUT, INDETERMINATE_CLASS, LOADING_CLASS, PAGE_TWO_CLASS, currentIndex; + var ACTIVE_CLASS, FILTER_INPUT, INDETERMINATE_CLASS, LOADING_CLASS, PAGE_TWO_CLASS, NON_SELECTABLE_CLASSES, SELECTABLE_CLASSES, currentIndex; LOADING_CLASS = "is-loading"; @@ -219,7 +218,7 @@ if (this.options.data) { if (_.isObject(this.options.data) && !_.isFunction(this.options.data)) { this.fullData = this.options.data; - currentIndex = -1 + currentIndex = -1; this.parseData(this.options.data); } else { this.remote = new GitLabDropdownRemote(this.options.data, { @@ -619,7 +618,7 @@ if ($el.length) { $el.first().trigger('click'); var href = $el.attr('href'); - if (href && href !== '#') Turbolinks.visit(href); + if (href && href !== '#') Turbolinks.visit(href); } }; @@ -655,8 +654,6 @@ return false; } if (currentKeyCode === 13 && currentIndex !== -1) { - e.preventDefault() - e.stopImmediatePropagation() return _this.selectRowAtIndex(currentIndex); } }; @@ -687,8 +684,8 @@ listItemBottom = listItemTop + listItemHeight; if (!index) { $dropdownContent.scrollTop(0) - } else if (index === ($listItems.length - 1)) { - $dropdownContent.scrollTop($dropdownContent.prop('scrollHeight')); + } else if (index === ($listItems.length - 1)) { + $dropdownContent.scrollTop($dropdownContent.prop('scrollHeight')); } else if (listItemBottom > (dropdownContentBottom + dropdownScrollTop)) { $dropdownContent.scrollTop(listItemBottom - dropdownContentBottom + CURSOR_SELECT_SCROLL_PADDING); } else if (listItemTop < (dropdownContentTop + dropdownScrollTop)) { diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index 37451d406ec..227e8c696b4 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -226,11 +226,11 @@ this.restoreOriginalState(); break; case KEYCODE.ENTER: - this.disableAutocomplete(); + this.disableAutocomplete(); break; - case KEYCODE.UP: + case KEYCODE.UP: case KEYCODE.DOWN: - return; + return; default: if (this.searchInput.val() === '') { this.disableAutocomplete(); -- cgit v1.2.1 From 0d3a9a6d31940a63ca450e3308f1e154ea4d2e5c Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Thu, 18 Aug 2016 21:26:45 -0500 Subject: make input name to be a function --- app/assets/javascripts/gl_dropdown.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index d3394fae3f9..2b8b934154e 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -470,7 +470,8 @@ } else { if (!selected) { value = this.options.id ? this.options.id(data) : data.id; - fieldName = this.options.fieldName; + fieldName = _.isFunction(this.options.fieldName) ? this.options.fieldName() : this.options.fieldName; + field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + value + "']"); if (field.length) { selected = true; @@ -533,7 +534,6 @@ GitLabDropdown.prototype.rowClicked = function(el) { var field, fieldName, groupName, isInput, selectedIndex, selectedObject, value; - fieldName = this.options.fieldName; isInput = $(this.el).is('input'); if (this.renderedData) { groupName = el.data('group'); @@ -545,6 +545,7 @@ selectedObject = this.renderedData[selectedIndex]; } } + fieldName = _.isFunction(this.options.fieldName) ? this.options.fieldName(selectedObject) : this.options.fieldName; value = this.options.id ? this.options.id(selectedObject, el) : selectedObject.id; if (isInput) { field = $(this.el); @@ -559,10 +560,9 @@ field.remove(); } if (this.options.toggleLabel) { - return this.updateLabel(selectedObject, el, this); - } else { - return selectedObject; + this.updateLabel(selectedObject, el, this); } + return selectedObject; } else if (el.hasClass(INDETERMINATE_CLASS)) { el.addClass(ACTIVE_CLASS); el.removeClass(INDETERMINATE_CLASS); @@ -570,7 +570,7 @@ field.remove(); } if (!field.length && fieldName) { - this.addInput(fieldName, value); + this.addInput(fieldName, value, selectedObject); } return selectedObject; } else { @@ -589,7 +589,7 @@ } if (value != null) { if (!field.length && fieldName) { - this.addInput(fieldName, value); + this.addInput(fieldName, value, selectedObject); } else { field.val(value).trigger('change'); } @@ -598,12 +598,15 @@ } }; - GitLabDropdown.prototype.addInput = function(fieldName, value) { + GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject) { var $input; $input = $('').attr('type', 'hidden').attr('name', fieldName).val(value); if (this.options.inputId != null) { $input.attr('id', this.options.inputId); } + if (selectedObject.type) { + $input.attr('data-type', selectedObject.type); + } return this.dropdown.before($input); }; -- cgit v1.2.1 From f3e12526e93a0b0269c41284138dc4381a24fcf8 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Fri, 19 Aug 2016 08:06:43 -0500 Subject: check if selectedObject is defined --- app/assets/javascripts/gl_dropdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 2b8b934154e..b7f27085b4f 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -604,7 +604,7 @@ if (this.options.inputId != null) { $input.attr('id', this.options.inputId); } - if (selectedObject.type) { + if (selectedObject && selectedObject.type) { $input.attr('data-type', selectedObject.type); } return this.dropdown.before($input); -- cgit v1.2.1 From a927a9bf6baa99be94181c3ab980947621ae2fe0 Mon Sep 17 00:00:00 2001 From: Gokmen Goksel Date: Mon, 25 Jul 2016 20:59:39 -0700 Subject: Support integration with Koding (online IDE) Koding: #index: landing page for Koding integration If enabled it will provide a link to open remote Koding instance url for now we are also providing the sneak preview video for how integration works in detail. Repository: check whether .koding.yml file exists on repository Projects: landing page: show Run in IDE (Koding) button if repo has stack file Projects: MR: show Run in IDE Koding button if repo has stack file on active branch ProjectHelpers: add_koding_stack: stack generator for provided project With this helper we will auto-generate the required stack template for a given project. For the feature we can request this base template from the running Koding instance on integration. Currently this will provide users to create a t2.nano instance on aws and it'll automatically configures the instance for basic requirements. Projects: empty state and landing page provide shortcuts to create stack projects_helper: use branch on checkout and provide an entry point This ${var.koding_queryString_branch} will be replaced with the branch provided in query string which will allow us to use same stack template for different branches of the same repository. ref: https://github.com/koding/koding/pull/8597/commits/b8c0e43c4c24bf132670aa8a3cfb0d634acfd09b projects_helper: provide sha info in query string to use existing vms With this change we'll be able to query existing vms on Koding side based on the commit id that they've created. ref: https://github.com/koding/koding/pull/8597/commits/1d630fadf31963fa6ccd3bed92e526761a30a343 Integration: Docs: Koding documentation added Disable /koding route if integration is disabled Use application settings to enable Koding Projects_helper: better indentation with strip_heredoc usage Projects_helper: return koding_url as is if there is no project provided current_settings: set koding_enabled: false by default Koding_Controller: to render not_found once integration is disabled Dashboard_specs: update spec for Koding enabled case Projects_Helper: make repo dynamic ref: https://github.com/koding/koding/pull/8597/commits/4d615242f45aaea4c4986be84ecc612b0bb1514c Updated documentation to have right format --- app/assets/images/koding-logo.svg | 8 ++++ .../admin/application_settings_controller.rb | 2 + app/controllers/koding_controller.rb | 15 ++++++ app/helpers/application_settings_helper.rb | 4 ++ app/helpers/projects_helper.rb | 54 ++++++++++++++++++++++ app/models/application_setting.rb | 6 +++ app/models/repository.rb | 10 +++- .../admin/application_settings/_form.html.haml | 19 ++++++++ app/views/koding/index.html.haml | 9 ++++ app/views/layouts/koding.html.haml | 5 ++ app/views/layouts/nav/_dashboard.html.haml | 5 ++ app/views/projects/buttons/_koding.html.haml | 7 +++ app/views/projects/merge_requests/_show.html.haml | 3 ++ app/views/projects/show.html.haml | 4 +- 14 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 app/assets/images/koding-logo.svg create mode 100644 app/controllers/koding_controller.rb create mode 100644 app/views/koding/index.html.haml create mode 100644 app/views/layouts/koding.html.haml create mode 100644 app/views/projects/buttons/_koding.html.haml (limited to 'app') diff --git a/app/assets/images/koding-logo.svg b/app/assets/images/koding-logo.svg new file mode 100644 index 00000000000..ad89d684d94 --- /dev/null +++ b/app/assets/images/koding-logo.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 9e1dc15de84..6ef7cf0bae6 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -109,6 +109,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :sentry_dsn, :akismet_enabled, :akismet_api_key, + :koding_enabled, + :koding_url, :email_author_in_body, :repository_checks_enabled, :metrics_packet_size, diff --git a/app/controllers/koding_controller.rb b/app/controllers/koding_controller.rb new file mode 100644 index 00000000000..bb89f3090f9 --- /dev/null +++ b/app/controllers/koding_controller.rb @@ -0,0 +1,15 @@ +class KodingController < ApplicationController + before_action :check_integration!, :authenticate_user!, :reject_blocked! + layout 'koding' + + def index + path = File.join(Rails.root, 'doc/integration/koding-usage.md') + @markdown = File.read(path) + end + + private + + def check_integration! + render_404 unless current_application_settings.koding_enabled? + end +end diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 78c0b79d2bd..6de25bea654 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -31,6 +31,10 @@ module ApplicationSettingsHelper current_application_settings.akismet_enabled? end + def koding_enabled? + current_application_settings.koding_enabled? + end + def allowed_protocols_present? current_application_settings.enabled_git_access_protocol.present? end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 505545fbabb..249d18c4486 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -236,6 +236,60 @@ module ProjectsHelper ) end + def add_koding_stack_path(project) + namespace_project_new_blob_path( + project.namespace, + project, + project.default_branch || 'master', + file_name: '.koding.yml', + commit_message: "Add Koding stack script", + content: <<-CONTENT.strip_heredoc + provider: + aws: + access_key: '${var.aws_access_key}' + secret_key: '${var.aws_secret_key}' + resource: + aws_instance: + #{project.path}-vm: + instance_type: t2.nano + user_data: |- + + # Created by GitLab UI for :> + + echo _KD_NOTIFY_@Installing Base packages...@ + + apt-get update -y + apt-get install git -y + + echo _KD_NOTIFY_@Cloning #{project.name}...@ + + export KODING_USER=${var.koding_user_username} + export REPO_URL=#{root_url}${var.koding_queryString_repo}.git + export BRANCH=${var.koding_queryString_branch} + + sudo -i -u $KODING_USER git clone $REPO_URL -b $BRANCH + + echo _KD_NOTIFY_@#{project.name} cloned.@ + CONTENT + ) + end + + def koding_project_url(project = nil, branch = nil, sha = nil) + if project + import_path = "/Home/Stacks/import" + + repo = project.path_with_namespace + branch ||= project.default_branch + sha ||= project.commit.short_id + + path = "#{import_path}?repo=#{repo}&branch=#{branch}&sha=#{sha}" + + return URI.join(current_application_settings.koding_url, path).to_s + end + + current_application_settings.koding_url + end + def contribution_guide_path(project) if project && contribution_guide = project.repository.contribution_guide namespace_project_blob_path( diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 8c19d9dc9c8..f0bcb2d7cda 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -55,6 +55,10 @@ class ApplicationSetting < ActiveRecord::Base presence: true, if: :akismet_enabled + validates :koding_url, + presence: true, + if: :koding_enabled + validates :max_attachment_size, presence: true, numericality: { only_integer: true, greater_than: 0 } @@ -149,6 +153,8 @@ class ApplicationSetting < ActiveRecord::Base two_factor_grace_period: 48, recaptcha_enabled: false, akismet_enabled: false, + koding_enabled: false, + koding_url: nil, repository_checks_enabled: true, disabled_oauth_sign_in_sources: [], send_user_confirmation_email: false, diff --git a/app/models/repository.rb b/app/models/repository.rb index 2494c266cd2..bdc3b9d1c1c 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -277,7 +277,7 @@ class Repository def cache_keys %i(size commit_count readme version contribution_guide changelog - license_blob license_key gitignore) + license_blob license_key gitignore koding_yml) end # Keys for data on branch/tag operations. @@ -553,6 +553,14 @@ class Repository end end + def koding_yml + return nil unless head_exists? + + cache.fetch(:koding_yml) do + file_on_head(/\A\.koding\.yml\z/) + end + end + def gitlab_ci_yml return nil unless head_exists? diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index c7fd344eea2..e0878512e62 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -388,6 +388,25 @@ .help-block If you got a lot of false alarms from repository checks you can choose to clear all repository check information from the database. + %fieldset + %legend Koding + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :koding_enabled do + = f.check_box :koding_enabled + Enable Koding + .form-group + = f.label :koding_url, 'Koding URL', class: 'control-label col-sm-2' + .col-sm-10 + = f.text_field :koding_url, class: 'form-control', placeholder: 'http://gitlab.your-koding-instance.com:8090' + .help-block + Koding has integration enabled out of the box for the + %strong gitlab + team, and you need to provide that team's URL here. Learn more in the + = succeed "." do + = link_to "Koding integration documentation", help_page_path("integration/koding") + .form-actions = f.submit 'Save', class: 'btn btn-save' diff --git a/app/views/koding/index.html.haml b/app/views/koding/index.html.haml new file mode 100644 index 00000000000..111cc67336c --- /dev/null +++ b/app/views/koding/index.html.haml @@ -0,0 +1,9 @@ +.row-content-block.second-block.center + %p + = icon('circle', class: 'cgreen') + Integration is active for + = link_to koding_project_url, target: '_blank' do + #{current_application_settings.koding_url} + +.documentation.wiki + = markdown @markdown diff --git a/app/views/layouts/koding.html.haml b/app/views/layouts/koding.html.haml new file mode 100644 index 00000000000..22319bba745 --- /dev/null +++ b/app/views/layouts/koding.html.haml @@ -0,0 +1,5 @@ +- page_title "Koding" +- page_description "Koding Dashboard" +- header_title "Koding", koding_path + += render template: "layouts/application" diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml index 3a14751ea8e..67f558c854b 100644 --- a/app/views/layouts/nav/_dashboard.html.haml +++ b/app/views/layouts/nav/_dashboard.html.haml @@ -12,6 +12,11 @@ = link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do %span Activity + - if koding_enabled? + = nav_link(controller: :koding) do + = link_to koding_path, title: 'Koding' do + %span + Koding = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do = link_to dashboard_groups_path, title: 'Groups' do %span diff --git a/app/views/projects/buttons/_koding.html.haml b/app/views/projects/buttons/_koding.html.haml new file mode 100644 index 00000000000..fdc80d44253 --- /dev/null +++ b/app/views/projects/buttons/_koding.html.haml @@ -0,0 +1,7 @@ +- if koding_enabled? && current_user && can_push_branch?(@project, @project.default_branch) + - if @repository.koding_yml + = link_to koding_project_url(@project), class: 'btn', target: '_blank' do + Run in IDE (Koding) + - else + = link_to add_koding_stack_path(@project), class: 'btn' do + Set Up Koding diff --git a/app/views/projects/merge_requests/_show.html.haml b/app/views/projects/merge_requests/_show.html.haml index f8025fc1dbe..9d8b4cc56be 100644 --- a/app/views/projects/merge_requests/_show.html.haml +++ b/app/views/projects/merge_requests/_show.html.haml @@ -16,6 +16,9 @@ - if @merge_request.open? .pull-right - if @merge_request.source_branch_exists? + - if koding_enabled? && @repository.koding_yml + = link_to koding_project_url(@merge_request.source_project, @merge_request.source_branch, @merge_request.commits.first.short_id), class: "btn inline btn-grouped btn-sm", target: '_blank' do + Run in IDE (Koding) = link_to "#modal_merge_info", class: "btn inline btn-grouped btn-sm", "data-toggle" => "modal" do Check out branch diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index a666d07e9eb..340e159c874 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -64,10 +64,12 @@ %li.missing = link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml') do Set Up CI + %li.project-repo-buttons-right .project-repo-buttons.project-right-buttons - if current_user = render 'shared/members/access_request_buttons', source: @project + = render "projects/buttons/koding" .btn-group.project-repo-btn-group = render "projects/buttons/download" @@ -86,4 +88,4 @@ Archived project! Repository is read-only %div{class: "project-show-#{default_project_view}"} - = render default_project_view \ No newline at end of file + = render default_project_view -- cgit v1.2.1 From 37bf35f0bcba28e271789542fb8c81a6c77236b6 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Tue, 26 Jul 2016 18:21:20 -0300 Subject: Todos sorting dropdown --- app/controllers/dashboard/todos_controller.rb | 1 + app/finders/todos_finder.rb | 6 +++++- app/models/concerns/issuable.rb | 19 ++++--------------- app/models/concerns/sortable.rb | 14 ++++++++++++++ app/models/todo.rb | 19 +++++++++++++++++++ app/views/dashboard/todos/index.html.haml | 19 +++++++++++++++++++ 6 files changed, 62 insertions(+), 16 deletions(-) (limited to 'app') diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb index 1243bb96d4d..9828d39869b 100644 --- a/app/controllers/dashboard/todos_controller.rb +++ b/app/controllers/dashboard/todos_controller.rb @@ -2,6 +2,7 @@ class Dashboard::TodosController < Dashboard::ApplicationController before_action :find_todos, only: [:index, :destroy_all] def index + @sort = params[:sort] @todos = @todos.page(params[:page]) end diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb index 4fe0070552e..37e919e6cf7 100644 --- a/app/finders/todos_finder.rb +++ b/app/finders/todos_finder.rb @@ -33,7 +33,7 @@ class TodosFinder # the project IDs yielded by the todos query thus far items = by_project(items) - items.reorder(id: :desc) + sort(items) end private @@ -106,6 +106,10 @@ class TodosFinder params[:type] end + def sort(items) + params[:sort] ? items.sort(params[:sort]) : items.reorder(id: :desc) + end + def by_action(items) if action? items = items.where(action: to_action_id) diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index cbae1cd439b..afb5ce37c06 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -131,7 +131,10 @@ module Issuable end def order_labels_priority(excluded_labels: []) - select("#{table_name}.*, (#{highest_label_priority(excluded_labels).to_sql}) AS highest_priority"). + condition_field = "#{table_name}.id" + highest_priority = highest_label_priority(name, condition_field, excluded_labels: excluded_labels).to_sql + + select("#{table_name}.*, (#{highest_priority}) AS highest_priority"). group(arel_table[:id]). reorder(Gitlab::Database.nulls_last_order('highest_priority', 'ASC')) end @@ -159,20 +162,6 @@ module Issuable grouping_columns end - - private - - def highest_label_priority(excluded_labels) - query = Label.select(Label.arel_table[:priority].minimum). - joins(:label_links). - where(label_links: { target_type: name }). - where("label_links.target_id = #{table_name}.id"). - reorder(nil) - - query.where.not(title: excluded_labels) if excluded_labels.present? - - query - end end def today? diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb index 8b47b9e0abd..1ebecd86af9 100644 --- a/app/models/concerns/sortable.rb +++ b/app/models/concerns/sortable.rb @@ -35,5 +35,19 @@ module Sortable all end end + + private + + def highest_label_priority(object_types, condition_field, excluded_labels: []) + query = Label.select(Label.arel_table[:priority].minimum). + joins(:label_links). + where(label_links: { target_type: object_types }). + where("label_links.target_id = #{condition_field}"). + reorder(nil) + + query.where.not(title: excluded_labels) if excluded_labels.present? + + query + end end end diff --git a/app/models/todo.rb b/app/models/todo.rb index 8d7a5965aa1..6ae9956ade5 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -1,4 +1,6 @@ class Todo < ActiveRecord::Base + include Sortable + ASSIGNED = 1 MENTIONED = 2 BUILD_FAILED = 3 @@ -41,6 +43,23 @@ class Todo < ActiveRecord::Base after_save :keep_around_commit + class << self + def sort(method) + method == "priority" ? order_by_labels_priority : order_by(method) + end + + # Order by priority depending on which issue/merge request the Todo belongs to + # Todos with highest priority first then oldest todos + # Need to order by created_at last because of differences on Mysql and Postgres when joining by type "Merge_request/Issue" + def order_by_labels_priority + highest_priority = highest_label_priority(["Issue", "MergeRequest"], "todos.target_id").to_sql + + select("#{table_name}.*, (#{highest_priority}) AS highest_priority"). + order(Gitlab::Database.nulls_last_order('highest_priority', 'ASC')). + order('todos.created_at') + end + end + def build_failed? action == BUILD_FAILED end diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 4e340b6ec16..d320d3bcc1e 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -43,6 +43,25 @@ class: 'select2 trigger-submit', include_blank: true, data: {placeholder: 'Action'}) + .pull-right + .dropdown.inline.prepend-left-10 + %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} + %span.light + - if @sort.present? + = sort_options_hash[@sort] + - else + = sort_title_recently_created + %b.caret + %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort + %li + = link_to todos_filter_path(sort: sort_value_priority) do + = sort_title_priority + = link_to todos_filter_path(sort: sort_value_recently_created) do + = sort_title_recently_created + = link_to todos_filter_path(sort: sort_value_oldest_created) do + = sort_title_oldest_created + + .prepend-top-default - if @todos.any? .js-todos-options{ data: {per_page: @todos.limit_value, current_page: @todos.current_page, total_pages: @todos.total_pages} } -- cgit v1.2.1 From d741303a5992b0d259a125baa62b66ca4df209da Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 19 Aug 2016 17:22:59 -0500 Subject: Call `set_discussion_id` again in DiffNote `before_validation` because the order is important --- app/models/diff_note.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app') diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb index aa54189fea9..c8320ff87fa 100644 --- a/app/models/diff_note.rb +++ b/app/models/diff_note.rb @@ -16,6 +16,9 @@ class DiffNote < Note after_initialize :ensure_original_discussion_id before_validation :set_original_position, :update_position, on: :create before_validation :set_line_code, :set_original_discussion_id + # We need to do this again, because it's already in `Note`, but is affected by + # `update_position` and needs to run after that. + before_validation :set_discussion_id after_save :keep_around_commits class << self -- cgit v1.2.1 From cf8efb462ea2aa909e9cb7e1118c160db1486949 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Fri, 19 Aug 2016 18:52:21 -0500 Subject: Use typeof instead of Underscore method --- app/assets/javascripts/gl_dropdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index b7f27085b4f..3f5c8359c22 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -470,7 +470,7 @@ } else { if (!selected) { value = this.options.id ? this.options.id(data) : data.id; - fieldName = _.isFunction(this.options.fieldName) ? this.options.fieldName() : this.options.fieldName; + fieldName = typeof this.options.fieldName === 'function' ? this.options.fieldName() : this.options.fieldName; field = this.dropdown.parent().find("input[name='" + fieldName + "'][value='" + value + "']"); if (field.length) { @@ -545,7 +545,7 @@ selectedObject = this.renderedData[selectedIndex]; } } - fieldName = _.isFunction(this.options.fieldName) ? this.options.fieldName(selectedObject) : this.options.fieldName; + fieldName = typeof this.options.fieldName === 'function' ? this.options.fieldName(selectedObject) : this.options.fieldName; value = this.options.id ? this.options.id(selectedObject, el) : selectedObject.id; if (isInput) { field = $(this.el); -- cgit v1.2.1 From 368569f51e1f2c8e406d392339e77f4b3ed08a7f Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Fri, 19 Aug 2016 19:42:10 -0500 Subject: Add element container to dropdowns --- .../protected_branches/_create_protected_branch.html.haml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/views/projects/protected_branches/_create_protected_branch.html.haml b/app/views/projects/protected_branches/_create_protected_branch.html.haml index d4c6fa24768..95d8743f546 100644 --- a/app/views/projects/protected_branches/_create_protected_branch.html.haml +++ b/app/views/projects/protected_branches/_create_protected_branch.html.haml @@ -22,16 +22,18 @@ %label.col-md-2.text-right{ for: 'merge_access_levels_attributes' } Allowed to merge: .col-md-10 - = dropdown_tag('Select', - options: { toggle_class: 'js-allowed-to-merge wide', - data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }}) + .js-allowed-to-merge-container + = dropdown_tag('Select', + options: { toggle_class: 'js-allowed-to-merge wide', + data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }}) .form-group %label.col-md-2.text-right{ for: 'push_access_levels_attributes' } Allowed to push: .col-md-10 - = dropdown_tag('Select', - options: { toggle_class: 'js-allowed-to-push wide', - data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes' }}) + .js-allowed-to-push-container + = dropdown_tag('Select', + options: { toggle_class: 'js-allowed-to-push wide', + data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes' }}) .panel-footer = f.submit 'Protect', class: 'btn-create btn', disabled: true -- cgit v1.2.1 From 97dddf39cd98d49f02b9adae3b7aeb3b28c434a6 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 19 Aug 2016 19:07:02 -0500 Subject: =?UTF-8?q?Disable=20=E2=80=9Cissue=20by=20email=E2=80=9D=20featur?= =?UTF-8?q?e=20until=20it=20uses=20a=20different=20token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/project.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index f9c48a546e6..1855760e694 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -611,7 +611,10 @@ class Project < ActiveRecord::Base end def new_issue_address(author) - if Gitlab::IncomingEmail.enabled? && author + # This feature is disabled for the time being. + return nil + + if Gitlab::IncomingEmail.enabled? && author # rubocop:disable Lint/UnreachableCode Gitlab::IncomingEmail.reply_address( "#{path_with_namespace}+#{author.authentication_token}") end -- cgit v1.2.1 From 41d89533e61f6009b5d800afc00c184e2807eafd Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 19 Aug 2016 22:22:52 -0700 Subject: Fix assorted rspec failures due to stale, cached user permissions RequestStore is disabled in tests, but the Ability class was caching user permissions based on the user and project ID of previous test runs. Revise code to use RequestStore only if it is active. --- app/models/ability.rb | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) (limited to 'app') diff --git a/app/models/ability.rb b/app/models/ability.rb index 07f703f205d..b82632ccc0b 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -166,38 +166,44 @@ class Ability end def project_abilities(user, project) - rules = [] key = "/user/#{user.id}/project/#{project.id}" - RequestStore.store[key] ||= begin - # Push abilities on the users team role - rules.push(*project_team_rules(project.team, user)) + if RequestStore.active? + RequestStore.store[key] ||= uncached_project_abilities(user, project) + else + uncached_project_abilities(user, project) + end + end - owner = user.admin? || - project.owner == user || - (project.group && project.group.has_owner?(user)) + def uncached_project_abilities(user, project) + rules = [] + # Push abilities on the users team role + rules.push(*project_team_rules(project.team, user)) - if owner - rules.push(*project_owner_rules) - end + owner = user.admin? || + project.owner == user || + (project.group && project.group.has_owner?(user)) - if project.public? || (project.internal? && !user.external?) - rules.push(*public_project_rules) + if owner + rules.push(*project_owner_rules) + end - # Allow to read builds for internal projects - rules << :read_build if project.public_builds? + if project.public? || (project.internal? && !user.external?) + rules.push(*public_project_rules) - unless owner || project.team.member?(user) || project_group_member?(project, user) - rules << :request_access if project.request_access_enabled - end - end + # Allow to read builds for internal projects + rules << :read_build if project.public_builds? - if project.archived? - rules -= project_archived_rules + unless owner || project.team.member?(user) || project_group_member?(project, user) + rules << :request_access if project.request_access_enabled end + end - rules - project_disabled_features_rules(project) + if project.archived? + rules -= project_archived_rules end + + rules - project_disabled_features_rules(project) end def project_team_rules(team, user) -- cgit v1.2.1 From 1954bb17eca49d375c92a4b8fa7f52fa39873a7d Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 20 Aug 2016 06:33:53 -0700 Subject: Make Ability#project_abilities return unique values and fix counts --- app/models/ability.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ability.rb b/app/models/ability.rb index b82632ccc0b..a49dd703926 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -203,7 +203,7 @@ class Ability rules -= project_archived_rules end - rules - project_disabled_features_rules(project) + (rules - project_disabled_features_rules(project)).uniq end def project_team_rules(team, user) -- cgit v1.2.1 From 561093e708ae79793c095820d1b595567a5bb145 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Fri, 19 Aug 2016 17:05:36 -0500 Subject: Fix project namespace links --- .../projects/ci/pipelines/_pipeline.html.haml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index 9a672b23341..b119f6edf14 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -1,23 +1,23 @@ - status = pipeline.status %tr.commit %td.commit-link - = link_to namespace_project_pipeline_path(@project.namespace, @project, pipeline.id) do + = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) do - if defined?(status_icon_only) && status_icon_only = ci_icon_for_status(status) - else = ci_status_with_icon(status) %td .branch-commit - = link_to namespace_project_pipeline_path(@project.namespace, @project, pipeline.id) do + = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) do %span ##{pipeline.id} - if pipeline.ref - unless defined?(hide_branch) && hide_branch .icon-container = pipeline.tag? ? icon('tag') : icon('code-fork') - = link_to pipeline.ref, namespace_project_commits_path(@project.namespace, @project, pipeline.ref), class: "monospace branch-name" + = link_to pipeline.ref, namespace_project_commits_path(pipeline.project.namespace, pipeline.project, pipeline.ref), class: "monospace branch-name" .icon-container = custom_icon("icon_commit") - = link_to pipeline.short_sha, namespace_project_commit_path(@project.namespace, @project, pipeline.sha), class: "commit-id monospace" + = link_to pipeline.short_sha, namespace_project_commit_path(pipeline.project.namespace, pipeline.project, pipeline.sha), class: "commit-id monospace" - if pipeline.latest? %span.label.label-success.has-tooltip{ title: 'Latest build for this branch' } latest - if pipeline.triggered? @@ -30,7 +30,7 @@ %p.commit-title - if commit = pipeline.commit = author_avatar(commit, size: 20) - = link_to_gfm truncate(commit.title, length: 60), namespace_project_commit_path(@project.namespace, @project, commit.id), class: "commit-row-message" + = link_to_gfm truncate(commit.title, length: 60), namespace_project_commit_path(pipeline.project.namespace, pipeline.project, commit.id), class: "commit-row-message" - else Cant find HEAD commit for this branch @@ -41,7 +41,7 @@ - status = stages_status[stage] - tooltip = "#{stage.titleize}: #{status || 'not found'}" - if status - = link_to namespace_project_pipeline_path(@project.namespace, @project, pipeline.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status}", title: tooltip do + = link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id, anchor: stage), class: "has-tooltip ci-status-icon-#{status}", title: tooltip do = ci_icon_for_status(status) - else .light.has-tooltip{ title: tooltip } @@ -71,7 +71,7 @@ %ul.dropdown-menu.dropdown-menu-align-right - actions.each do |build| %li - = link_to play_namespace_project_build_path(@project.namespace, @project, build), method: :post, rel: 'nofollow' do + = link_to play_namespace_project_build_path(pipeline.project.namespace, pipeline.project, build), method: :post, rel: 'nofollow' do = icon("play") %span= build.name.humanize - if artifacts.present? @@ -82,15 +82,15 @@ %ul.dropdown-menu.dropdown-menu-align-right - artifacts.each do |build| %li - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do + = link_to download_namespace_project_build_artifacts_path(pipeline.project.namespace, pipeline.project, build), rel: 'nofollow' do = icon("download") %span Download '#{build.name}' artifacts - - if can?(current_user, :update_pipeline, @project) + - if can?(current_user, :update_pipeline, pipeline.project) .cancel-retry-btns.inline - if pipeline.retryable? - = link_to retry_namespace_project_pipeline_path(@project.namespace, @project, pipeline.id), class: 'btn has-tooltip', title: "Retry", method: :post do + = link_to retry_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: 'btn has-tooltip', title: "Retry", method: :post do = icon("repeat") - if pipeline.cancelable? - = link_to cancel_namespace_project_pipeline_path(@project.namespace, @project, pipeline.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do + = link_to cancel_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do = icon("remove") -- cgit v1.2.1 From 5cb488e8a1a10432c1c5a322b2d4748cb754277f Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 20 Aug 2016 09:18:06 -0700 Subject: Fix Error 500 resulting when loading network graph `discussion_id` may not be present when the SELECT call for notes does not include this attribute. Don't attempt to set the discussion ID unless the model contains the attribute. Closes #21119, #21128 --- app/models/note.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/models/note.rb b/app/models/note.rb index 3bbf5db0b70..f2656df028b 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -259,6 +259,8 @@ class Note < ActiveRecord::Base def ensure_discussion_id return unless self.persisted? + # Needed in case the SELECT statement doesn't ask for `discussion_id` + return unless self.has_attribute?(:discussion_id) return if self.discussion_id set_discussion_id -- cgit v1.2.1 From acba6042835707d8cbc4d4074ea1ebc3dae690bd Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Sat, 20 Aug 2016 23:02:43 -0500 Subject: Fix inputs not being found due to incorrect class in wrap element --- .../projects/protected_branches/_create_protected_branch.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/projects/protected_branches/_create_protected_branch.html.haml b/app/views/projects/protected_branches/_create_protected_branch.html.haml index 95d8743f546..16ac75c3d37 100644 --- a/app/views/projects/protected_branches/_create_protected_branch.html.haml +++ b/app/views/projects/protected_branches/_create_protected_branch.html.haml @@ -22,7 +22,7 @@ %label.col-md-2.text-right{ for: 'merge_access_levels_attributes' } Allowed to merge: .col-md-10 - .js-allowed-to-merge-container + .merge_access_levels-container = dropdown_tag('Select', options: { toggle_class: 'js-allowed-to-merge wide', data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }}) @@ -30,7 +30,7 @@ %label.col-md-2.text-right{ for: 'push_access_levels_attributes' } Allowed to push: .col-md-10 - .js-allowed-to-push-container + .push_access_levels-container = dropdown_tag('Select', options: { toggle_class: 'js-allowed-to-push wide', data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes' }}) -- cgit v1.2.1 From 54412dac15203b9208ca3ab56617262e7968050b Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Sun, 21 Aug 2016 00:18:28 -0500 Subject: Make dropdown selectables This makes dropdown to look according the dropdowns on the edit form. This options add a tick mark next to the selected option. --- .../projects/protected_branches/_create_protected_branch.html.haml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/views/projects/protected_branches/_create_protected_branch.html.haml b/app/views/projects/protected_branches/_create_protected_branch.html.haml index 95d8743f546..226f8311a90 100644 --- a/app/views/projects/protected_branches/_create_protected_branch.html.haml +++ b/app/views/projects/protected_branches/_create_protected_branch.html.haml @@ -25,6 +25,7 @@ .js-allowed-to-merge-container = dropdown_tag('Select', options: { toggle_class: 'js-allowed-to-merge wide', + dropdown_class: 'dropdown-menu-selectable', data: { field_name: 'protected_branch[merge_access_levels_attributes][0][access_level]', input_id: 'merge_access_levels_attributes' }}) .form-group %label.col-md-2.text-right{ for: 'push_access_levels_attributes' } @@ -33,6 +34,7 @@ .js-allowed-to-push-container = dropdown_tag('Select', options: { toggle_class: 'js-allowed-to-push wide', + dropdown_class: 'dropdown-menu-selectable', data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes' }}) .panel-footer -- cgit v1.2.1 From 18e98a364388e53786c7fe01eaff75efa496bb4c Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Sun, 21 Aug 2016 00:19:22 -0500 Subject: Do not update if one dropdown has not selected any option No need to update the branch permission if no option is marked on the dropdown --- app/assets/javascripts/protected_branch_edit.js.es6 | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app') diff --git a/app/assets/javascripts/protected_branch_edit.js.es6 b/app/assets/javascripts/protected_branch_edit.js.es6 index a59fcbfa082..40bc4adb71b 100644 --- a/app/assets/javascripts/protected_branch_edit.js.es6 +++ b/app/assets/javascripts/protected_branch_edit.js.es6 @@ -31,6 +31,9 @@ const $allowedToMergeInput = this.$wrap.find(`input[name="${this.$allowedToMergeDropdown.data('fieldName')}"]`); const $allowedToPushInput = this.$wrap.find(`input[name="${this.$allowedToPushDropdown.data('fieldName')}"]`); + // Do not update if one dropdown has not selected any option + if (!($allowedToMergeInput.length && $allowedToPushInput.length)) return; + $.ajax({ type: 'POST', url: this.$wrap.data('url'), -- cgit v1.2.1 From 4a4d8608e8a09e0c55f690aeefc05f742bc67011 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Sun, 21 Aug 2016 00:20:57 -0500 Subject: Toggle dropdown disabled attribute Before this the dropdowns were not being disabled if the user unselected an option from the allowed to merge/push dropdowns. --- app/assets/javascripts/protected_branch_create.js.es6 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/protected_branch_create.js.es6 b/app/assets/javascripts/protected_branch_create.js.es6 index 2efca2414dc..46beca469b9 100644 --- a/app/assets/javascripts/protected_branch_create.js.es6 +++ b/app/assets/javascripts/protected_branch_create.js.es6 @@ -47,9 +47,7 @@ const $allowedToMergeInput = this.$wrap.find('input[name="protected_branch[merge_access_levels_attributes][0][access_level]"]'); const $allowedToPushInput = this.$wrap.find('input[name="protected_branch[push_access_levels_attributes][0][access_level]"]'); - if ($branchInput.val() && $allowedToMergeInput.val() && $allowedToPushInput.val()){ - this.$form.find('input[type="submit"]').removeAttr('disabled'); - } + this.$form.find('input[type="submit"]').attr('disabled', !($branchInput.val() && $allowedToMergeInput.length && $allowedToPushInput.length)); } } -- cgit v1.2.1 From a7d7e9a51889a276f2d057207fba8d095fa8fc8d Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Sun, 21 Aug 2016 00:21:32 -0500 Subject: Set default label if user unselects the option from dropdown --- app/assets/javascripts/protected_branch_access_dropdown.js.es6 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/protected_branch_access_dropdown.js.es6 b/app/assets/javascripts/protected_branch_access_dropdown.js.es6 index 2fbb088fa04..7aeb5f92514 100644 --- a/app/assets/javascripts/protected_branch_access_dropdown.js.es6 +++ b/app/assets/javascripts/protected_branch_access_dropdown.js.es6 @@ -10,8 +10,12 @@ selectable: true, inputId: $dropdown.data('input-id'), fieldName: $dropdown.data('field-name'), - toggleLabel(item) { - return item.text; + toggleLabel(item, el) { + if (el.is('.is-active')) { + return item.text; + } else { + return 'Select'; + } }, clicked(item, $el, e) { e.preventDefault(); -- cgit v1.2.1 From a816281fcb41a428bedd44997cf58cbc52e2d111 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Sun, 21 Aug 2016 22:15:05 -0500 Subject: Remove tab stop from issuable form added by description templates --- app/views/shared/issuable/_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 544ed6203aa..7b8f95a86ee 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -42,7 +42,7 @@ - if can_add_template?(issuable) %p.help-block Add - = link_to "description templates", help_page_path('user/project/description_templates') + = link_to "description templates", help_page_path('user/project/description_templates'), tabindex: -1 to help your contributors communicate effectively! .form-group.detail-page-description -- cgit v1.2.1 From eb355dec8768ef128795309c6c9ffa296a6eee22 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 22 Aug 2016 14:18:58 +0300 Subject: Restore diff_sha_refs method Signed-off-by: Dmitriy Zaporozhets --- app/models/diff_note.rb | 6 +++++- app/models/merge_request.rb | 31 ++++++++++++++++--------------- 2 files changed, 21 insertions(+), 16 deletions(-) (limited to 'app') diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb index 0c23c1c1934..c8320ff87fa 100644 --- a/app/models/diff_note.rb +++ b/app/models/diff_note.rb @@ -118,7 +118,11 @@ class DiffNote < Note end def noteable_diff_refs - noteable.diff_refs + if noteable.respond_to?(:diff_sha_refs) + noteable.diff_sha_refs + else + noteable.diff_refs + end end def set_original_position diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 14b785e6bd4..615e550cf05 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -265,28 +265,29 @@ class MergeRequest < ActiveRecord::Base @source_branch_sha || source_branch_head.try(:sha) end - def branch_merge_base_sha - branch_merge_base_commit.try(:sha) + def diff_refs + return unless diff_start_commit || diff_base_commit + + Gitlab::Diff::DiffRefs.new( + base_sha: diff_base_sha, + start_sha: diff_start_sha, + head_sha: diff_head_sha + ) end - def diff_refs + # Return diff_refs instance trying to not touch the git repository + def diff_sha_refs if merge_request_diff && merge_request_diff.diff_refs_by_sha? merge_request_diff.diff_refs else - start_sha = target_branch_sha - head_sha = source_branch_sha - base_sha = branch_merge_base_sha - - if start_sha || base_sha - Gitlab::Diff::DiffRefs.new( - base_sha: base_sha, - start_sha: start_sha, - head_sha: head_sha - ) - end + diff_refs end end + def branch_merge_base_sha + branch_merge_base_commit.try(:sha) + end + def validate_branches if target_project == source_project && target_branch == source_branch errors.add :branch_conflict, "You can not use same project/branch for source and target" @@ -748,7 +749,7 @@ class MergeRequest < ActiveRecord::Base end def has_complete_diff_refs? - diff_refs && diff_refs.complete? + diff_sha_refs && diff_sha_refs.complete? end def update_diff_notes_positions(old_diff_refs:, new_diff_refs:) -- cgit v1.2.1 From 9020d8d19edf344d18cddce7d209448bcdbdabdc Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 22 Aug 2016 16:02:24 +0300 Subject: Change location of slash commands in notes widget --- app/views/projects/notes/_hints.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/notes/_hints.html.haml b/app/views/projects/notes/_hints.html.haml index cf6e14648cc..f4212350c2d 100644 --- a/app/views/projects/notes/_hints.html.haml +++ b/app/views/projects/notes/_hints.html.haml @@ -5,7 +5,7 @@ = link_to 'Markdown', help_page_path('markdown/markdown'), target: '_blank', tabindex: -1 - if supports_slash_commands and - = link_to 'slash commands', help_page_path('workflow/slash_commands'), target: '_blank', tabindex: -1 + = link_to 'slash commands', help_page_path('user/project/slash_commands'), target: '_blank', tabindex: -1 are - else is -- cgit v1.2.1 From 1804f60fd5a1aab92f553b7c66b79857ef35df35 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Thu, 18 Aug 2016 22:34:17 +0300 Subject: Change images to reflect current status, add link to inline docs --- app/views/shared/issuable/_label_page_default.html.haml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/shared/issuable/_label_page_default.html.haml b/app/views/shared/issuable/_label_page_default.html.haml index a76b7baf918..18b50f9da7b 100644 --- a/app/views/shared/issuable/_label_page_default.html.haml +++ b/app/views/shared/issuable/_label_page_default.html.haml @@ -8,7 +8,13 @@ - if show_boards_content .issue-board-dropdown-content %p - Each label that exists in your issue tracker can have its own dedicated list. Select a label below to add a list to your Board and it will automatically be populated with issues that have that label. To create a list for a label that doesn't exist yet, simply create the label below. + Each label that exists in your issue tracker can have its own dedicated + list. Select a label below to add a list to your Board and it will + automatically be populated with issues that have that label. To create + a list for a label that doesn't exist yet, simply create the label below. + Learn more in the + = succeed "." do + = link_to "Issue Boards documentation", help_page_path("user/project/issue_board"), class: "underlined-link" = dropdown_filter(filter_placeholder) = dropdown_content - if @project && show_footer -- cgit v1.2.1 From 6ba9050a7db5585cd4ffc9cdfe95fc64446613ac Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 22 Aug 2016 15:03:26 +0300 Subject: Remove link to docs from new list text --- app/views/shared/issuable/_label_page_default.html.haml | 3 --- 1 file changed, 3 deletions(-) (limited to 'app') diff --git a/app/views/shared/issuable/_label_page_default.html.haml b/app/views/shared/issuable/_label_page_default.html.haml index 18b50f9da7b..c0dc63be2bf 100644 --- a/app/views/shared/issuable/_label_page_default.html.haml +++ b/app/views/shared/issuable/_label_page_default.html.haml @@ -12,9 +12,6 @@ list. Select a label below to add a list to your Board and it will automatically be populated with issues that have that label. To create a list for a label that doesn't exist yet, simply create the label below. - Learn more in the - = succeed "." do - = link_to "Issue Boards documentation", help_page_path("user/project/issue_board"), class: "underlined-link" = dropdown_filter(filter_placeholder) = dropdown_content - if @project && show_footer -- cgit v1.2.1 From 915dda1421d8227c0ba395bfdb04ff915724c4ac Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 22 Aug 2016 17:09:15 +0300 Subject: Split Koding admin/user docs --- app/controllers/koding_controller.rb | 2 +- app/views/admin/application_settings/_form.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/koding_controller.rb b/app/controllers/koding_controller.rb index bb89f3090f9..f3759b4c0ea 100644 --- a/app/controllers/koding_controller.rb +++ b/app/controllers/koding_controller.rb @@ -3,7 +3,7 @@ class KodingController < ApplicationController layout 'koding' def index - path = File.join(Rails.root, 'doc/integration/koding-usage.md') + path = File.join(Rails.root, 'doc/user/project/koding.md') @markdown = File.read(path) end diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index e0878512e62..d929364fc96 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -405,7 +405,7 @@ %strong gitlab team, and you need to provide that team's URL here. Learn more in the = succeed "." do - = link_to "Koding integration documentation", help_page_path("integration/koding") + = link_to "Koding administration documentation", help_page_path("administration/integration/koding") .form-actions -- cgit v1.2.1 From 49c8530ea7c6d2d23ceca3cba78d62bc45b2c6ef Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 22 Aug 2016 17:36:04 +0300 Subject: Remove documentation rendering from /koding for now --- app/views/koding/index.html.haml | 3 --- 1 file changed, 3 deletions(-) (limited to 'app') diff --git a/app/views/koding/index.html.haml b/app/views/koding/index.html.haml index 111cc67336c..65887aacbaf 100644 --- a/app/views/koding/index.html.haml +++ b/app/views/koding/index.html.haml @@ -4,6 +4,3 @@ Integration is active for = link_to koding_project_url, target: '_blank' do #{current_application_settings.koding_url} - -.documentation.wiki - = markdown @markdown -- cgit v1.2.1 From 7b3fd81673e595b48b4c0e5f1ca5f1ab806f8ac3 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Mon, 22 Aug 2016 18:21:28 +0300 Subject: Disable comments on older merge request diff Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/merge_requests_controller.rb | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app') diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 438dd928853..eff959c781c 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -93,6 +93,11 @@ class Projects::MergeRequestsController < Projects::ApplicationController respond_to do |format| format.html { define_discussion_vars } format.json do + if @merge_request_diff != @merge_request.merge_request_diff + # Disable comments if browsing older version of the diff + @diff_notes_disabled = true + end + @diffs = @merge_request_diff.diffs(diff_options) render json: { html: view_to_html_string("projects/merge_requests/show/_diffs") } -- cgit v1.2.1 From 8f9a7ca854ffda26c5ce9aed2aec10bf155d0463 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Mon, 1 Aug 2016 18:34:17 +0300 Subject: Revert the revert of Optimistic Locking --- app/controllers/projects/issues_controller.rb | 6 +++++- app/controllers/projects/merge_requests_controller.rb | 5 ++++- app/models/concerns/issuable.rb | 6 ++++++ app/views/shared/issuable/_form.html.haml | 9 +++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 639cf4c0ef2..7b0189150f8 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -125,6 +125,10 @@ class Projects::IssuesController < Projects::ApplicationController render json: @issue.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) end end + + rescue ActiveRecord::StaleObjectError + @conflict = true + render :edit end def referenced_merge_requests @@ -230,7 +234,7 @@ class Projects::IssuesController < Projects::ApplicationController def issue_params params.require(:issue).permit( :title, :assignee_id, :position, :description, :confidential, - :milestone_id, :due_date, :state_event, :task_num, label_ids: [] + :milestone_id, :due_date, :state_event, :task_num, :lock_version, label_ids: [] ) end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index d3fe441c4d2..6a8c7166b39 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -258,6 +258,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController else render "edit" end + rescue ActiveRecord::StaleObjectError + @conflict = true + render :edit end def remove_wip @@ -493,7 +496,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController :title, :assignee_id, :source_project_id, :source_branch, :target_project_id, :target_branch, :milestone_id, :state_event, :description, :task_num, :force_remove_source_branch, - label_ids: [] + :lock_version, label_ids: [] ) end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index afb5ce37c06..8e11d4f57cf 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -87,6 +87,12 @@ module Issuable User.find(assignee_id_was).update_cache_counts if assignee_id_was assignee.update_cache_counts if assignee end + + # We want to use optimistic lock for cases when only title or description are involved + # http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html + def locking_enabled? + title_changed? || description_changed? + end end module ClassMethods diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 544ed6203aa..d8cfa1fca72 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -1,5 +1,12 @@ = form_errors(issuable) +- if @conflict + .alert.alert-danger + Someone edited the #{issuable.class.model_name.human.downcase} the same time you did. + Please check out + = link_to "the #{issuable.class.model_name.human.downcase}", polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), target: "_blank" + and make sure your changes will not unintentionally remove theirs + .form-group = f.label :title, class: 'control-label' @@ -172,3 +179,5 @@ = link_to 'Delete', polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), data: { confirm: "#{issuable.class.name.titleize} will be removed! Are you sure?" }, method: :delete, class: 'btn btn-danger btn-grouped' = link_to 'Cancel', polymorphic_path([@project.namespace.becomes(Namespace), @project, issuable]), class: 'btn btn-grouped btn-cancel' + += f.hidden_field :lock_version -- cgit v1.2.1 From d4e44e90943b842de97df21946cf19a7ffecee83 Mon Sep 17 00:00:00 2001 From: John Northrup Date: Mon, 22 Aug 2016 15:25:05 -0500 Subject: fix location of markdown help location --- app/views/projects/notes/_hints.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/notes/_hints.html.haml b/app/views/projects/notes/_hints.html.haml index f4212350c2d..6c14f48d41b 100644 --- a/app/views/projects/notes/_hints.html.haml +++ b/app/views/projects/notes/_hints.html.haml @@ -2,7 +2,7 @@ .comment-toolbar.clearfix .toolbar-text Styling with - = link_to 'Markdown', help_page_path('markdown/markdown'), target: '_blank', tabindex: -1 + = link_to 'Markdown', help_page_path('user/markdown'), target: '_blank', tabindex: -1 - if supports_slash_commands and = link_to 'slash commands', help_page_path('user/project/slash_commands'), target: '_blank', tabindex: -1 -- cgit v1.2.1 From 7e6af85490e289ffcc868390654748009ecc67fa Mon Sep 17 00:00:00 2001 From: Patricio Cano Date: Mon, 22 Aug 2016 21:36:04 -0500 Subject: Also check if Akismet is enabled, before showing the `Submit as spam` button. --- app/models/concerns/spammable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/concerns/spammable.rb b/app/models/concerns/spammable.rb index ce54fe5d3bf..1aa97debe42 100644 --- a/app/models/concerns/spammable.rb +++ b/app/models/concerns/spammable.rb @@ -23,7 +23,7 @@ module Spammable def submittable_as_spam? if user_agent_detail - user_agent_detail.submittable? + user_agent_detail.submittable? && current_application_settings.akismet_enabled else false end -- cgit v1.2.1 From e665444724cd5d213d2d2d37267c3ded08912296 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 23 Aug 2016 01:06:54 -0700 Subject: Fix incorrect "stopped impersonation" log message Closes #21015 --- app/controllers/admin/impersonations_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/admin/impersonations_controller.rb b/app/controllers/admin/impersonations_controller.rb index 8be35f00a77..9433da02f64 100644 --- a/app/controllers/admin/impersonations_controller.rb +++ b/app/controllers/admin/impersonations_controller.rb @@ -7,7 +7,7 @@ class Admin::ImpersonationsController < Admin::ApplicationController warden.set_user(impersonator, scope: :user) - Gitlab::AppLogger.info("User #{original_user.username} has stopped impersonating #{impersonator.username}") + Gitlab::AppLogger.info("User #{impersonator.username} has stopped impersonating #{original_user.username}") session[:impersonator_id] = nil -- cgit v1.2.1 From 2c909a5a3c219cad6e6ef8c78a4984ab311d14cb Mon Sep 17 00:00:00 2001 From: Bryce Date: Tue, 23 Aug 2016 10:39:31 +0200 Subject: Check for pipelines when setting page_gutter_class. --- app/helpers/nav_helper.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb index 6c1cc6ef072..2b0ff6c0d00 100644 --- a/app/helpers/nav_helper.rb +++ b/app/helpers/nav_helper.rb @@ -25,6 +25,8 @@ module NavHelper current_path?('merge_requests#commits') || current_path?('merge_requests#builds') || current_path?('merge_requests#conflicts') || + current_path?('merge_requests#pipelines') || + current_path?('issues#show') if cookies[:collapsed_gutter] == 'true' "page-gutter right-sidebar-collapsed" -- cgit v1.2.1 From 1a7c293c2ddbe960accec355a0ed399de82e0c41 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 22 Aug 2016 17:19:39 +0100 Subject: Fix file links on project page Files view --- app/controllers/projects_controller.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index fc52cd2f367..2a6385c1029 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -5,7 +5,7 @@ class ProjectsController < Projects::ApplicationController before_action :project, except: [:new, :create] before_action :repository, except: [:new, :create] before_action :assign_ref_vars, only: [:show], if: :repo_exists? - before_action :tree, only: [:show], if: [:repo_exists?, :project_view_files?] + before_action :assign_tree_vars, only: [:show], if: [:repo_exists?, :project_view_files?] # Authorize before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export] @@ -332,4 +332,11 @@ class ProjectsController < Projects::ApplicationController def get_id project.repository.root_ref end + + # ExtractsPath will set @id = project.path on the show route, but it has to be the + # branch name for the tree view to work correctly. + def assign_tree_vars + @id = get_id + tree + end end -- cgit v1.2.1 From 5963263912c1633ff49ce758f71589bae8133e57 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 19 Aug 2016 09:45:58 +0100 Subject: Fixed enter key in search input not working Closes #20627 --- app/assets/javascripts/gl_dropdown.js | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 24abea0d30d..b1f5a6816e1 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -31,8 +31,8 @@ this.input .on('keydown', function (e) { var keyCode = e.which; - if (keyCode === 13) { - e.preventDefault(); + if (keyCode === 13 && !options.elIsInput) { + e.preventDefault() } }) .on('keyup', function(e) { @@ -46,7 +46,7 @@ } else if (this.input.val() === "" && $inputContainer.hasClass(HAS_VALUE_CLASS)) { $inputContainer.removeClass(HAS_VALUE_CLASS); } - if (keyCode === 13) { + if (keyCode === 13 && !options.elIsInput) { return false; } if (this.options.remote) { @@ -238,6 +238,7 @@ } if (this.options.filterable) { this.filter = new GitLabDropdownFilter(this.filterInput, { + elIsInput: $(this.el).is('input'), filterInputBlur: this.filterInputBlur, filterByText: this.options.filterByText, onFilter: this.options.onFilter, @@ -266,8 +267,12 @@ if (_this.dropdown.find('.dropdown-toggle-page').length) { selector = ".dropdown-page-one " + selector; } - $(selector, _this.dropdown).first().find('a').addClass('is-focused'); - return currentIndex = 0; + if ($(_this.el).is('input')) { + currentIndex = -1; + } else { + $(selector, _this.dropdown).first().find('a').addClass('is-focused'); + currentIndex = 0; + } } }; })(this) @@ -611,17 +616,20 @@ return this.dropdown.before($input); }; - GitLabDropdown.prototype.selectRowAtIndex = function(index) { + GitLabDropdown.prototype.selectRowAtIndex = function() { var $el, selector; - selector = SELECTABLE_CLASSES + ":eq(" + index + ") a"; + selector = ".dropdown-content .is-focused"; if (this.dropdown.find(".dropdown-toggle-page").length) { selector = ".dropdown-page-one " + selector; } $el = $(selector, this.dropdown); if ($el.length) { - $el.first().trigger('click'); var href = $el.attr('href'); - if (href && href !== '#') Turbolinks.visit(href); + if (href && href !== '#') { + Turbolinks.visit(href); + } else { + $el.first().trigger('click'); + } } }; @@ -657,7 +665,7 @@ return false; } if (currentKeyCode === 13 && currentIndex !== -1) { - return _this.selectRowAtIndex(currentIndex); + _this.selectRowAtIndex(); } }; })(this)); -- cgit v1.2.1 From 86f03e175042afe551cf95c195c043fa92b58ea7 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Mon, 22 Aug 2016 11:41:51 -0500 Subject: Allow passing an index to selectRowAtIndex --- app/assets/javascripts/gl_dropdown.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index b1f5a6816e1..0179b320a3b 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -616,9 +616,14 @@ return this.dropdown.before($input); }; - GitLabDropdown.prototype.selectRowAtIndex = function() { + GitLabDropdown.prototype.selectRowAtIndex = function(index) { var $el, selector; - selector = ".dropdown-content .is-focused"; + // If we pass an option index + if (typeof index !== "undefined") { + selector = SELECTABLE_CLASSES + ":eq(" + index + ") a"; + } else { + selector = ".dropdown-content .is-focused"; + } if (this.dropdown.find(".dropdown-toggle-page").length) { selector = ".dropdown-page-one " + selector; } -- cgit v1.2.1 From cc94714c05a5088db7e30b9582a187e5ee52068b Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Tue, 23 Aug 2016 08:45:18 -0500 Subject: Add body as data-container on pipeline graph tooltip --- app/helpers/ci_status_helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb index bb285a17baf..0327b476d18 100644 --- a/app/helpers/ci_status_helper.rb +++ b/app/helpers/ci_status_helper.rb @@ -66,10 +66,10 @@ module CiStatusHelper Ci::Runner.shared.blank? end - def render_status_with_link(type, status, path = nil, tooltip_placement: 'auto left', cssclass: '') + def render_status_with_link(type, status, path = nil, tooltip_placement: 'auto left', cssclass: '', container: 'body') klass = "ci-status-link ci-status-icon-#{status.dasherize} #{cssclass}" title = "#{type.titleize}: #{ci_label_for_status(status)}" - data = { toggle: 'tooltip', placement: tooltip_placement } + data = { toggle: 'tooltip', placement: tooltip_placement, container: container } if path link_to ci_icon_for_status(status), path, -- cgit v1.2.1 From 7d654c0e1810f2023a1deaeddd542c5c92d20f42 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Fri, 5 Aug 2016 13:02:08 +0100 Subject: Added addtional 'renderable' validator to check 'data-note-type' attr exists --- app/assets/javascripts/files_comment_button.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/files_comment_button.js b/app/assets/javascripts/files_comment_button.js index b2e49b71fec..817d38ea86e 100644 --- a/app/assets/javascripts/files_comment_button.js +++ b/app/assets/javascripts/files_comment_button.js @@ -39,12 +39,13 @@ FilesCommentButton.prototype.render = function(e) { var $currentTarget, buttonParentElement, lineContentElement, textFileElement; $currentTarget = $(e.currentTarget); + buttonParentElement = this.getButtonParent($currentTarget); - if (!this.shouldRender(e, buttonParentElement)) { - return; - } - textFileElement = this.getTextFileElement($currentTarget); + if (!this.validateButtonParent(buttonParentElement)) return; lineContentElement = this.getLineContent($currentTarget); + if (!this.validateLineContent(lineContentElement)) return; + + textFileElement = this.getTextFileElement($currentTarget); buttonParentElement.append(this.buildButton({ noteableType: textFileElement.attr('data-noteable-type'), noteableID: textFileElement.attr('data-noteable-id'), @@ -119,10 +120,14 @@ return newButtonParent.is(this.getButtonParent($(e.currentTarget))); }; - FilesCommentButton.prototype.shouldRender = function(e, buttonParentElement) { + FilesCommentButton.prototype.validateButtonParent = function(buttonParentElement) { return !buttonParentElement.hasClass(EMPTY_CELL_CLASS) && !buttonParentElement.hasClass(UNFOLDABLE_LINE_CLASS) && $(COMMENT_BUTTON_CLASS, buttonParentElement).length === 0; }; + FilesCommentButton.prototype.validateLineContent = function(lineContentElement) { + return lineContentElement.attr('data-note-type') && lineContentElement.attr('data-note-type') !== ''; + }; + return FilesCommentButton; })(); -- cgit v1.2.1 From 84d2cab648d06cdeb8ace31727bb16abe9ef67c1 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Sat, 20 Aug 2016 17:21:59 +0100 Subject: Moved builds panel to the bottom of the builds sidemenu --- app/assets/stylesheets/pages/builds.scss | 3 +- app/views/projects/builds/_sidebar.html.haml | 69 ++++++++++++++-------------- 2 files changed, 36 insertions(+), 36 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index c1bb250b42d..1af4e388386 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -131,7 +131,7 @@ } .build-dropdown { - padding: 0 $gl-padding; + padding: $gl-padding 0; .dropdown-menu-toggle { margin-top: 8px; @@ -145,7 +145,6 @@ } .builds-container { - margin-top: $gl-padding; background-color: $white-light; border-top: 1px solid $border-color; border-bottom: 1px solid $border-color; diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml index 5b0b58e087b..ab66f757a55 100644 --- a/app/views/projects/builds/_sidebar.html.haml +++ b/app/views/projects/builds/_sidebar.html.haml @@ -1,3 +1,6 @@ +- builds = @build.pipeline.builds.latest.to_a +- statuses = ["failed", "pending", "running", "canceled", "success", "skipped"] + %aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar .block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default Build @@ -11,40 +14,6 @@ %p.build-detail-row #{@build.coverage}% - - builds = @build.pipeline.builds.latest.to_a - - statuses = ["failed", "pending", "running", "canceled", "success", "skipped"] - - if builds.size > 1 - .dropdown.build-dropdown - .build-light-text Stage - %button.dropdown-menu-toggle{type: 'button', 'data-toggle' => 'dropdown'} - %span.stage-selection More - = icon('caret-down') - %ul.dropdown-menu - - builds.map(&:stage).uniq.each do |stage| - %li - %a.stage-item= stage - - .builds-container - - statuses.each do |build_status| - - builds.select{|build| build.status == build_status}.each do |build| - .build-job{class: ('active' if build == @build), data: {stage: build.stage}} - = link_to namespace_project_build_path(@project.namespace, @project, build) do - = icon('check') - = ci_icon_for_status(build.status) - %span - - if build.name - = build.name - - else - = build.id - - - if @build.retried? - %li.active - %a - Build ##{@build.id} - · - %i.fa.fa-warning - This build was retried. - .blocks-container - if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?) .block{ class: ("block-first" if !@build.coverage) } @@ -141,3 +110,35 @@ - @build.tag_list.each do |tag| %span.label.label-primary = tag + + - if builds.size > 1 + .dropdown.build-dropdown + .title Stage + %button.dropdown-menu-toggle{type: 'button', 'data-toggle' => 'dropdown'} + %span.stage-selection More + = icon('caret-down') + %ul.dropdown-menu + - builds.map(&:stage).uniq.each do |stage| + %li + %a.stage-item= stage + + .builds-container + - statuses.each do |build_status| + - builds.select{|build| build.status == build_status}.each do |build| + .build-job{class: ('active' if build == @build), data: {stage: build.stage}} + = link_to namespace_project_build_path(@project.namespace, @project, build) do + = icon('check') + = ci_icon_for_status(build.status) + %span + - if build.name + = build.name + - else + = build.id + + - if @build.retried? + %li.active + %a + Build ##{@build.id} + · + %i.fa.fa-warning + This build was retried. -- cgit v1.2.1 From 8a07b45d64f4e96fd39d51edd8b921c4515edc1f Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Sat, 20 Aug 2016 17:47:58 +0100 Subject: Changed `retry` link to blue --- app/assets/stylesheets/pages/builds.scss | 7 +++++++ app/views/projects/builds/_sidebar.html.haml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 1af4e388386..87e195018b9 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -122,6 +122,13 @@ } } + .retry-link { + color: $gl-link-color; + &:hover { + text-decoration: underline; + } + } + .stage-item { cursor: pointer; diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml index ab66f757a55..c35bfe703e8 100644 --- a/app/views/projects/builds/_sidebar.html.haml +++ b/app/views/projects/builds/_sidebar.html.haml @@ -45,7 +45,7 @@ .title Build details - if can?(current_user, :update_build, @build) && @build.retryable? - = link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'pull-right', method: :post + = link_to "Retry", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'pull-right retry-link', method: :post - if @build.merge_request %p.build-detail-row %span.build-light-text Merge Request: -- cgit v1.2.1 From c369738e78570d4c951765728c3c5510f0d68b68 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Tue, 23 Aug 2016 15:19:36 +0100 Subject: Review changes --- app/assets/stylesheets/pages/builds.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 87e195018b9..10dfae74d96 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -107,7 +107,7 @@ } .blocks-container { - padding: $gl-padding; + padding: 0 $gl-padding; } .block { -- cgit v1.2.1 From 009727fb80da7c3c2f4414b1e4d0a31c9e13ff68 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Mon, 22 Aug 2016 13:43:21 -0500 Subject: Remove ugly horizontal scrollbars in windows --- app/assets/stylesheets/pages/builds.scss | 2 +- app/assets/stylesheets/pages/pipelines.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index c1bb250b42d..8c33e7d9a2e 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -150,7 +150,7 @@ border-top: 1px solid $border-color; border-bottom: 1px solid $border-color; max-height: 300px; - overflow: scroll; + overflow: auto; svg { position: relative; diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 6fa097e3bf1..8e7cfafe76f 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -265,7 +265,7 @@ .pipeline-visualization { position: relative; - min-width: 1220px; + min-width: 1200px; ul { padding: 0; -- cgit v1.2.1 From 2f4cde01c2849168c5cb1aea3902e0af8bcaced1 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Mon, 22 Aug 2016 13:51:38 -0500 Subject: Remove graph min width --- app/assets/stylesheets/pages/pipelines.scss | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 8e7cfafe76f..7eb4e7ec676 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -265,7 +265,6 @@ .pipeline-visualization { position: relative; - min-width: 1200px; ul { padding: 0; -- cgit v1.2.1 From a60c1fc4f8e315d82fddf157b5f4790ed8409d1e Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Tue, 23 Aug 2016 20:08:18 +0100 Subject: Added unfold test to parallel and added 'diff discussion' context --- app/assets/javascripts/files_comment_button.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/files_comment_button.js b/app/assets/javascripts/files_comment_button.js index 817d38ea86e..3fb3b1a8b51 100644 --- a/app/assets/javascripts/files_comment_button.js +++ b/app/assets/javascripts/files_comment_button.js @@ -125,7 +125,7 @@ }; FilesCommentButton.prototype.validateLineContent = function(lineContentElement) { - return lineContentElement.attr('data-note-type') && lineContentElement.attr('data-note-type') !== ''; + return lineContentElement.attr('data-discussion-id') && lineContentElement.attr('data-discussion-id') !== ''; }; return FilesCommentButton; -- cgit v1.2.1 From 3a9091b43d06ab499968571bfa13e1c613114e4d Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Tue, 23 Aug 2016 15:02:16 -0500 Subject: Fix overflow scroll --- app/assets/stylesheets/pages/merge_requests.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index fcdaf671538..4bfdc4a2b26 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -269,7 +269,7 @@ .builds { .table-holder { - overflow-x: scroll; + overflow-x: auto; } } -- cgit v1.2.1 From e65bc0f175c54d9df66fd4950972c0b0b08d448e Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 24 Aug 2016 16:02:56 +0800 Subject: Path could also have slashes! Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_14347729 --- app/controllers/projects/artifacts_controller.rb | 14 +++++++++++--- app/helpers/gitlab_routing_helper.rb | 5 +++-- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 60e432d68d8..17c6d56c8b9 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -1,4 +1,6 @@ class Projects::ArtifactsController < Projects::ApplicationController + include ExtractsPath + layout 'project' before_action :authorize_read_build! before_action :authorize_update_build!, only: [:keep] @@ -35,7 +37,8 @@ class Projects::ArtifactsController < Projects::ApplicationController end def latest_succeeded - target_path = artifacts_action_path(params[:path], project, build) + path = ref_name_and_path.last + target_path = artifacts_action_path(path, project, build) if target_path redirect_to(target_path) @@ -59,13 +62,18 @@ class Projects::ArtifactsController < Projects::ApplicationController end def build_from_ref - if params[:ref_name] - builds = project.latest_successful_builds_for(params[:ref_name]) + if params[:ref_name_and_path] + ref_name = ref_name_and_path.first + builds = project.latest_successful_builds_for(ref_name) builds.find_by(name: params[:job]) end end + def ref_name_and_path + @ref_name_and_path ||= extract_ref(params[:ref_name_and_path]) + end + def artifacts_file @artifacts_file ||= build.artifacts_file end diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index cd526f17b99..a322a90cc4e 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -153,9 +153,10 @@ module GitlabRoutingHelper # Artifacts def artifacts_action_path(path, project, build) - args = [project.namespace, project, build] + action, path_params = path.split('/', 2) + args = [project.namespace, project, build, path_params] - case path + case action when 'download' download_namespace_project_build_artifacts_path(*args) when 'browse' -- cgit v1.2.1 From 0762f680c653dff9ff45fe0ce72136b39e125979 Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Mon, 22 Aug 2016 13:56:07 +0100 Subject: change from members using size to start using total_count in the group members page --- app/views/groups/group_members/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index 90f362c052b..f789796e942 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -17,7 +17,7 @@ .panel-heading %strong #{@group.name} group members - %span.badge= @members.size + %span.badge= @members.total_count .controls = form_tag group_group_members_path(@group), method: :get, class: 'form-inline member-search-form' do .form-group -- cgit v1.2.1 From ddbdf4e609c70dc6ed88860b5e1e65abde69ee94 Mon Sep 17 00:00:00 2001 From: winniehell Date: Wed, 24 Aug 2016 02:22:30 +0200 Subject: Restore get_id in ExtractsPath --- app/controllers/projects_controller.rb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'app') diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 2a6385c1029..fc52cd2f367 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -5,7 +5,7 @@ class ProjectsController < Projects::ApplicationController before_action :project, except: [:new, :create] before_action :repository, except: [:new, :create] before_action :assign_ref_vars, only: [:show], if: :repo_exists? - before_action :assign_tree_vars, only: [:show], if: [:repo_exists?, :project_view_files?] + before_action :tree, only: [:show], if: [:repo_exists?, :project_view_files?] # Authorize before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export] @@ -332,11 +332,4 @@ class ProjectsController < Projects::ApplicationController def get_id project.repository.root_ref end - - # ExtractsPath will set @id = project.path on the show route, but it has to be the - # branch name for the tree view to work correctly. - def assign_tree_vars - @id = get_id - tree - end end -- cgit v1.2.1 From 8f197315b3ec354cb0cc0af4acbe54d6aa01d71b Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Wed, 24 Aug 2016 19:09:10 +0800 Subject: Aggressively merge views, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_14347679 https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_14347470 --- app/assets/stylesheets/framework/lists.scss | 4 --- app/views/projects/branches/_branch.html.haml | 10 +----- app/views/projects/buttons/_artifacts.html.haml | 14 -------- app/views/projects/buttons/_download.html.haml | 38 ++++++++++++++++++---- .../repositories/_download_archive.html.haml | 28 ---------------- app/views/projects/show.html.haml | 4 +-- app/views/projects/tags/_download.html.haml | 15 --------- app/views/projects/tags/_tag.html.haml | 3 +- app/views/projects/tags/show.html.haml | 3 +- app/views/projects/tree/show.html.haml | 3 +- 10 files changed, 37 insertions(+), 85 deletions(-) delete mode 100644 app/views/projects/buttons/_artifacts.html.haml delete mode 100644 app/views/projects/repositories/_download_archive.html.haml delete mode 100644 app/views/projects/tags/_download.html.haml (limited to 'app') diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index a88c7906f5d..965fcc06518 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -162,10 +162,6 @@ ul.content-list { margin-right: 0; } } - - .artifacts-btn { - margin-right: 10px; - } } // When dragging a list item diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 21ac675ffe0..c5549f86e38 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -27,15 +27,7 @@ = link_to namespace_project_compare_index_path(@project.namespace, @project, from: @repository.root_ref, to: branch.name), class: 'btn btn-default', method: :post, title: "Compare" do Compare - - if @project.latest_successful_builds_for(branch.name).any? - .dropdown.inline.artifacts-btn - %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } - = icon('download') - %span.caret - %span.sr-only - Select Archive Format - %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } - = render 'projects/buttons/artifacts', project: @project, ref: branch.name + = render 'projects/buttons/download', project: @project, ref: branch.name - if can_remove_branch?(@project, branch.name) = link_to namespace_project_branch_path(@project.namespace, @project, branch.name), class: 'btn btn-remove remove-row has-tooltip', title: "Delete branch", method: :delete, data: { confirm: "Deleting the '#{branch.name}' branch cannot be undone. Are you sure?", container: 'body' }, remote: true do diff --git a/app/views/projects/buttons/_artifacts.html.haml b/app/views/projects/buttons/_artifacts.html.haml deleted file mode 100644 index a52677ebf0a..00000000000 --- a/app/views/projects/buttons/_artifacts.html.haml +++ /dev/null @@ -1,14 +0,0 @@ -- pipeline = project.pipelines.latest_successful_for(ref) -- if pipeline - - artifacts = pipeline.builds.latest.with_artifacts - - if artifacts.any? - %li.dropdown-header Artifacts - - unless pipeline.latest? - - latest_pipeline = project.pipeline_for(ref) - %li - .unclickable= ci_status_for_statuseable(latest_pipeline) - %li.dropdown-header Previous Artifacts - - artifacts.each do |job| - %li - = link_to latest_succeeded_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do - %span Download '#{job.name}' diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 5e748c44b08..73dcb9c079e 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -1,17 +1,41 @@ -- unless @project.empty_repo? - - if can? current_user, :download_code, @project - .dropdown.inline.btn-group +- if !project.empty_repo? && can?(current_user, :download_code, project) + %span.btn-group{class: 'hidden-xs hidden-sm btn-grouped'} + .dropdown.inline %button.btn{ 'data-toggle' => 'dropdown' } = icon('download') - = icon('caret-down') + %span.caret %span.sr-only Select Archive Format %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } %li.dropdown-header Source code %li - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'zip'), rel: 'nofollow' do + = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'zip'), rel: 'nofollow' do + %i.fa.fa-download %span Download zip %li - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: @ref, format: 'tar.gz'), rel: 'nofollow' do + = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do + %i.fa.fa-download %span Download tar.gz - = render 'projects/buttons/artifacts', project: @project, ref: @ref + %li + = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.bz2'), rel: 'nofollow' do + %i.fa.fa-download + %span Download tar.bz2 + %li + = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar'), rel: 'nofollow' do + %i.fa.fa-download + %span Download tar + + - pipeline = project.pipelines.latest_successful_for(ref) + - if pipeline + - artifacts = pipeline.builds.latest.with_artifacts + - if artifacts.any? + %li.dropdown-header Artifacts + - unless pipeline.latest? + - latest_pipeline = project.pipeline_for(ref) + %li + .unclickable= ci_status_for_statuseable(latest_pipeline) + %li.dropdown-header Previous Artifacts + - artifacts.each do |job| + %li + = link_to latest_succeeded_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do + %span Download '#{job.name}' diff --git a/app/views/projects/repositories/_download_archive.html.haml b/app/views/projects/repositories/_download_archive.html.haml deleted file mode 100644 index 4f40696a190..00000000000 --- a/app/views/projects/repositories/_download_archive.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -- ref = ref || nil -- btn_class = btn_class || '' -%span.btn-group{class: btn_class} - .dropdown.inline - %button.btn{ 'data-toggle' => 'dropdown' } - = icon('download') - %span.caret - %span.sr-only - Select Archive Format - %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } - %li.dropdown-header Source code - %li - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'zip'), rel: 'nofollow' do - %i.fa.fa-download - %span Download zip - %li - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do - %i.fa.fa-download - %span Download tar.gz - %li - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar.bz2'), rel: 'nofollow' do - %i.fa.fa-download - %span Download tar.bz2 - %li - = link_to archive_namespace_project_repository_path(@project.namespace, @project, ref: ref, format: 'tar'), rel: 'nofollow' do - %i.fa.fa-download - %span Download tar - = render 'projects/buttons/artifacts', project: @project, ref: ref diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index a666d07e9eb..7130ebaa743 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -70,7 +70,7 @@ = render 'shared/members/access_request_buttons', source: @project .btn-group.project-repo-btn-group - = render "projects/buttons/download" + = render 'projects/buttons/download', project: @project, ref: @ref = render 'projects/buttons/dropdown' = render 'shared/notifications/button', notification_setting: @notification_setting @@ -86,4 +86,4 @@ Archived project! Repository is read-only %div{class: "project-show-#{default_project_view}"} - = render default_project_view \ No newline at end of file + = render default_project_view diff --git a/app/views/projects/tags/_download.html.haml b/app/views/projects/tags/_download.html.haml deleted file mode 100644 index 6985eb74ca7..00000000000 --- a/app/views/projects/tags/_download.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -.dropdown.inline - %a.btn.dropdown-toggle{ 'data-toggle' => 'dropdown' } - = icon('download') - %span.caret - %span.sr-only - Select Archive Format - %ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' } - %li.dropdown-header Source code - %li - = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'zip'), rel: 'nofollow' do - %span Download zip - %li - = link_to archive_namespace_project_repository_path(project.namespace, project, ref: ref, format: 'tar.gz'), rel: 'nofollow' do - %span Download tar.gz - = render 'projects/buttons/artifacts', project: project, ref: ref diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml index 2c11c0e5b21..a156d98bab8 100644 --- a/app/views/projects/tags/_tag.html.haml +++ b/app/views/projects/tags/_tag.html.haml @@ -11,8 +11,7 @@ = strip_gpg_signature(tag.message) .controls - - if can?(current_user, :download_code, @project) - = render 'projects/tags/download', ref: tag.name, project: @project + = render 'projects/buttons/download', project: @project, ref: tag.name - if can?(current_user, :push_code, @project) = link_to edit_namespace_project_tag_release_path(@project.namespace, @project, tag.name), class: 'btn has-tooltip', title: "Edit release notes", data: { container: "body" } do diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml index 395d7af6cbb..4dd7439b2d0 100644 --- a/app/views/projects/tags/show.html.haml +++ b/app/views/projects/tags/show.html.haml @@ -12,8 +12,7 @@ = icon('files-o') = link_to namespace_project_commits_path(@project.namespace, @project, @tag.name), class: 'btn has-tooltip', title: 'Browse commits' do = icon('history') - - if can? current_user, :download_code, @project - = render 'projects/tags/download', ref: @tag.name, project: @project + = render 'projects/buttons/download', project: @project, ref: @tag.name - if can?(current_user, :admin_project, @project) .pull-right = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has-tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index c68f86f1378..37d341212af 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -10,8 +10,7 @@ %div{ class: container_class } .tree-controls = render 'projects/find_file_link' - - if can? current_user, :download_code, @project - = render 'projects/repositories/download_archive', ref: @ref, btn_class: 'hidden-xs hidden-sm btn-grouped' + = render 'projects/buttons/download', project: @project, ref: @ref #tree-holder.tree-holder.clearfix .nav-block -- cgit v1.2.1 From 5ddb51ba5a4c58db86645424211783af4e390166 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Wed, 24 Aug 2016 11:25:06 +0000 Subject: Update abuse_reports.js.es6 with prettier `window.gl` assignment --- app/assets/javascripts/abuse_reports.js.es6 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/abuse_reports.js.es6 b/app/assets/javascripts/abuse_reports.js.es6 index 748084b0307..2fe46b9fd06 100644 --- a/app/assets/javascripts/abuse_reports.js.es6 +++ b/app/assets/javascripts/abuse_reports.js.es6 @@ -1,4 +1,3 @@ -window.gl = window.gl || {}; ((global) => { const MAX_MESSAGE_LENGTH = 500; const MESSAGE_CELL_SELECTOR = '.abuse-reports .message'; @@ -36,4 +35,4 @@ window.gl = window.gl || {}; } global.AbuseReports = AbuseReports; -})(window.gl); +})(window.gl || (window.gl = {})); -- cgit v1.2.1 From 831fc817a62d66f4ac4eac8e8cc0b76d593e6448 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Wed, 24 Aug 2016 15:51:33 +0100 Subject: Moved `.option-hidden` to exist only in `SELECTABLE_CLASSES` as `NON_SELECTABLE_CLASSES` is used to re-show previously hidden elements --- app/assets/javascripts/gl_dropdown.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 0179b320a3b..2daf1b77e13 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -117,7 +117,7 @@ } }); } else { - return elements.show(); + return elements.show().removeClass('option-hidden'); } } }; @@ -190,9 +190,9 @@ currentIndex = -1; - NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link, .option-hidden'; + NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-link'; - SELECTABLE_CLASSES = ".dropdown-content li:not(" + NON_SELECTABLE_CLASSES + ")"; + SELECTABLE_CLASSES = ".dropdown-content li:not(" + NON_SELECTABLE_CLASSES + ", .option-hidden)"; CURSOR_SELECT_SCROLL_PADDING = 5 -- cgit v1.2.1 From 3c09000e18dcbf6a74ed1f749db3184e309cf081 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 10 Aug 2016 18:22:21 -0300 Subject: Does not halt the GitHub import process when an error occurs --- app/models/project.rb | 2 -- app/workers/repository_import_worker.rb | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/project.rb b/app/models/project.rb index 1855760e694..8cf093be4c3 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -471,8 +471,6 @@ class Project < ActiveRecord::Base end def reset_cache_and_import_attrs - update(import_error: nil) - ProjectCacheWorker.perform_async(self.id) self.import_data.destroy if self.import_data diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index e6701078f71..d2ca8813ab9 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -14,6 +14,8 @@ class RepositoryImportWorker import_url: @project.import_url, path: @project.path_with_namespace) + project.update_column(:import_error, nil) + result = Projects::ImportService.new(project, current_user).execute if result[:status] == :error -- cgit v1.2.1 From 4f13a7935f24f258fde8288671ba2447639df446 Mon Sep 17 00:00:00 2001 From: winniehell Date: Thu, 18 Aug 2016 02:00:28 +0200 Subject: Remove green outline from `New branch unavailable` button on issue page (!5858) --- app/assets/javascripts/issue.js | 3 +-- app/views/projects/issues/_new_branch.html.haml | 17 ++++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js index 6838d9d8da1..e6422602ce8 100644 --- a/app/assets/javascripts/issue.js +++ b/app/assets/javascripts/issue.js @@ -127,7 +127,7 @@ Issue.prototype.initCanCreateBranch = function() { var $container; - $container = $('div#new-branch'); + $container = $('#new-branch'); if ($container.length === 0) { return; } @@ -139,7 +139,6 @@ if (data.can_create_branch) { $container.find('.checking').hide(); $container.find('.available').show(); - return $container.find('a').attr('disabled', false); } else { $container.find('.checking').hide(); return $container.find('.unavailable').show(); diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml index 24749699c6d..33556a1a2b3 100644 --- a/app/views/projects/issues/_new_branch.html.haml +++ b/app/views/projects/issues/_new_branch.html.haml @@ -1,13 +1,12 @@ - if can?(current_user, :push_code, @project) .pull-right #new-branch{'data-path' => can_create_branch_namespace_project_issue_path(@project.namespace, @project, @issue)} + = link_to '#', class: 'checking btn btn-grouped', disabled: 'disabled' do + = icon('spinner spin') + Checking branches = link_to namespace_project_branches_path(@project.namespace, @project, branch_name: @issue.to_branch_name, issue_iid: @issue.iid), - method: :post, class: 'btn btn-new btn-inverted has-tooltip', title: @issue.to_branch_name, disabled: 'disabled' do - .checking - = icon('spinner spin') - Checking branches - .available.hide - New branch - .unavailable.hide - = icon('exclamation-triangle') - New branch unavailable + method: :post, class: 'btn btn-new btn-inverted btn-grouped has-tooltip available hide', title: @issue.to_branch_name do + New branch + = link_to '#', class: 'unavailable btn btn-grouped hide', disabled: 'disabled' do + = icon('exclamation-triangle') + New branch unavailable -- cgit v1.2.1 From 60ac1167d1324b4468e3ae85000feb2bf78a24e2 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Wed, 24 Aug 2016 11:29:18 -0500 Subject: Remove max height on pipelines graph --- app/assets/stylesheets/pages/pipelines.scss | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 6fa097e3bf1..dcb3e48d686 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -254,7 +254,6 @@ width: 100%; overflow: auto; white-space: nowrap; - max-height: 500px; transition: max-height 0.3s, padding 0.3s; &.graph-collapsed { -- cgit v1.2.1 From cfe512d6e926a3f757d18e5269214c06b8f9643d Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Wed, 24 Aug 2016 13:13:26 +0200 Subject: Show "Create Merge Request" widget for push events to fork projects on the source project --- app/helpers/projects_helper.rb | 21 +++++++++++---------- app/models/user.rb | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'app') diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 249d18c4486..356f27f2d5d 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -116,6 +116,17 @@ module ProjectsHelper license.nickname || license.name end + def last_push_event + return unless current_user + + project_ids = [@project.id] + if fork = current_user.fork_of(@project) + project_ids << fork.id + end + + current_user.recent_push(project_ids) + end + private def get_project_nav_tabs(project, current_user) @@ -351,16 +362,6 @@ module ProjectsHelper namespace_project_new_blob_path(@project.namespace, @project, tree_join(ref), file_name: 'LICENSE') end - def last_push_event - return unless current_user - - if fork = current_user.fork_of(@project) - current_user.recent_push(fork.id) - else - current_user.recent_push(@project.id) - end - end - def readme_cache_key sha = @project.commit.try(:sha) || 'nil' [@project.path_with_namespace, sha, "readme"].join('-') diff --git a/app/models/user.rb b/app/models/user.rb index 48e83ab7e56..ad3cfbc03e4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -489,10 +489,10 @@ class User < ActiveRecord::Base (personal_projects.count.to_f / projects_limit) * 100 end - def recent_push(project_id = nil) + def recent_push(project_ids = nil) # Get push events not earlier than 2 hours ago events = recent_events.code_push.where("created_at > ?", Time.now - 2.hours) - events = events.where(project_id: project_id) if project_id + events = events.where(project_id: project_ids) if project_ids # Use the latest event that has not been pushed or merged recently events.recent.find do |event| -- cgit v1.2.1 From 170885edd6f3ea52792511586778e0dce8021cf7 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 18 Aug 2016 17:06:33 -0700 Subject: Add Sentry logging to API calls Closes #21043 --- app/controllers/application_controller.rb | 23 +---------------------- app/helpers/sentry_helper.rb | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 app/helpers/sentry_helper.rb (limited to 'app') diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 634d36a4467..70a2275592b 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -6,6 +6,7 @@ class ApplicationController < ActionController::Base include Gitlab::GonHelper include GitlabRoutingHelper include PageLayoutHelper + include SentryHelper include WorkhorseHelper before_action :authenticate_user_from_private_token! @@ -46,28 +47,6 @@ class ApplicationController < ActionController::Base protected - def sentry_context - if Rails.env.production? && current_application_settings.sentry_enabled - if current_user - Raven.user_context( - id: current_user.id, - email: current_user.email, - username: current_user.username, - ) - end - - Raven.tags_context(program: sentry_program_context) - end - end - - def sentry_program_context - if Sidekiq.server? - 'sidekiq' - else - 'rails' - end - end - # This filter handles both private tokens and personal access tokens def authenticate_user_from_private_token! token_string = params[:private_token].presence || request.headers['PRIVATE-TOKEN'].presence diff --git a/app/helpers/sentry_helper.rb b/app/helpers/sentry_helper.rb new file mode 100644 index 00000000000..f8cccade15b --- /dev/null +++ b/app/helpers/sentry_helper.rb @@ -0,0 +1,27 @@ +module SentryHelper + def sentry_enabled? + Rails.env.production? && current_application_settings.sentry_enabled? + end + + def sentry_context + return unless sentry_enabled? + + if current_user + Raven.user_context( + id: current_user.id, + email: current_user.email, + username: current_user.username, + ) + end + + Raven.tags_context(program: sentry_program_context) + end + + def sentry_program_context + if Sidekiq.server? + 'sidekiq' + else + 'rails' + end + end +end -- cgit v1.2.1 From 1bc53bc8702ea0cda02a368ba9ca0516ad1e3947 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Wed, 24 Aug 2016 19:29:25 -0500 Subject: Ensure we update the label after input is added --- app/assets/javascripts/gl_dropdown.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 0179b320a3b..521ffb405be 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -565,10 +565,6 @@ } else { field.remove(); } - if (this.options.toggleLabel) { - this.updateLabel(selectedObject, el, this); - } - return selectedObject; } else if (el.hasClass(INDETERMINATE_CLASS)) { el.addClass(ACTIVE_CLASS); el.removeClass(INDETERMINATE_CLASS); @@ -578,7 +574,6 @@ if (!field.length && fieldName) { this.addInput(fieldName, value, selectedObject); } - return selectedObject; } else { if (!this.options.multiSelect || el.hasClass('dropdown-clear-active')) { this.dropdown.find("." + ACTIVE_CLASS).removeClass(ACTIVE_CLASS); @@ -590,9 +585,6 @@ field.remove(); } el.addClass(ACTIVE_CLASS); - if (this.options.toggleLabel) { - this.updateLabel(selectedObject, el, this); - } if (value != null) { if (!field.length && fieldName) { this.addInput(fieldName, value, selectedObject); @@ -600,8 +592,14 @@ field.val(value).trigger('change'); } } - return selectedObject; } + + // Update label right after input has been added + if (this.options.toggleLabel) { + this.updateLabel(selectedObject, el, this); + } + + return selectedObject; }; GitLabDropdown.prototype.addInput = function(fieldName, value, selectedObject) { -- cgit v1.2.1 From 23bed91b3fb21a92b836011677cc75c884188f10 Mon Sep 17 00:00:00 2001 From: De Wet Blomerus Date: Thu, 25 Aug 2016 04:55:32 +0200 Subject: rename Statuseable to HasStatus --- app/models/ci/pipeline.rb | 2 +- app/models/commit_status.rb | 2 +- app/models/concerns/has_status.rb | 93 +++++++++++++++++++++++++++++ app/models/concerns/statuseable.rb | 93 ----------------------------- app/services/ci/process_pipeline_service.rb | 2 +- 5 files changed, 96 insertions(+), 96 deletions(-) create mode 100644 app/models/concerns/has_status.rb delete mode 100644 app/models/concerns/statuseable.rb (limited to 'app') diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 087abe4cbb1..255fb33bdeb 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -1,7 +1,7 @@ module Ci class Pipeline < ActiveRecord::Base extend Ci::Model - include Statuseable + include HasStatus self.table_name = 'ci_commits' diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 84ceeac7d3e..9114af18496 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -1,5 +1,5 @@ class CommitStatus < ActiveRecord::Base - include Statuseable + include HasStatus include Importable self.table_name = 'ci_builds' diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb new file mode 100644 index 00000000000..f7b8352405c --- /dev/null +++ b/app/models/concerns/has_status.rb @@ -0,0 +1,93 @@ +module HasStatus + extend ActiveSupport::Concern + + AVAILABLE_STATUSES = %w[created pending running success failed canceled skipped] + STARTED_STATUSES = %w[running success failed skipped] + ACTIVE_STATUSES = %w[pending running] + COMPLETED_STATUSES = %w[success failed canceled] + + class_methods do + def status_sql + scope = all.relevant + builds = scope.select('count(*)').to_sql + success = scope.success.select('count(*)').to_sql + ignored = scope.ignored.select('count(*)').to_sql if scope.respond_to?(:ignored) + ignored ||= '0' + pending = scope.pending.select('count(*)').to_sql + running = scope.running.select('count(*)').to_sql + canceled = scope.canceled.select('count(*)').to_sql + skipped = scope.skipped.select('count(*)').to_sql + + deduce_status = "(CASE + WHEN (#{builds})=0 THEN NULL + WHEN (#{builds})=(#{skipped}) THEN 'skipped' + WHEN (#{builds})=(#{success})+(#{ignored})+(#{skipped}) THEN 'success' + WHEN (#{builds})=(#{pending})+(#{skipped}) THEN 'pending' + WHEN (#{builds})=(#{canceled})+(#{success})+(#{ignored})+(#{skipped}) THEN 'canceled' + WHEN (#{running})+(#{pending})>0 THEN 'running' + ELSE 'failed' + END)" + + deduce_status + end + + def status + all.pluck(self.status_sql).first + end + + def started_at + all.minimum(:started_at) + end + + def finished_at + all.maximum(:finished_at) + end + end + + included do + validates :status, inclusion: { in: AVAILABLE_STATUSES } + + state_machine :status, initial: :created do + state :created, value: 'created' + state :pending, value: 'pending' + state :running, value: 'running' + state :failed, value: 'failed' + state :success, value: 'success' + state :canceled, value: 'canceled' + state :skipped, value: 'skipped' + end + + scope :created, -> { where(status: 'created') } + scope :relevant, -> { where.not(status: 'created') } + scope :running, -> { where(status: 'running') } + scope :pending, -> { where(status: 'pending') } + scope :success, -> { where(status: 'success') } + scope :failed, -> { where(status: 'failed') } + scope :canceled, -> { where(status: 'canceled') } + scope :skipped, -> { where(status: 'skipped') } + scope :running_or_pending, -> { where(status: [:running, :pending]) } + scope :finished, -> { where(status: [:success, :failed, :canceled]) } + end + + def started? + STARTED_STATUSES.include?(status) && started_at + end + + def active? + ACTIVE_STATUSES.include?(status) + end + + def complete? + COMPLETED_STATUSES.include?(status) + end + + private + + def calculate_duration + if started_at && finished_at + finished_at - started_at + elsif started_at + Time.now - started_at + end + end +end diff --git a/app/models/concerns/statuseable.rb b/app/models/concerns/statuseable.rb deleted file mode 100644 index 750f937b724..00000000000 --- a/app/models/concerns/statuseable.rb +++ /dev/null @@ -1,93 +0,0 @@ -module Statuseable - extend ActiveSupport::Concern - - AVAILABLE_STATUSES = %w[created pending running success failed canceled skipped] - STARTED_STATUSES = %w[running success failed skipped] - ACTIVE_STATUSES = %w[pending running] - COMPLETED_STATUSES = %w[success failed canceled] - - class_methods do - def status_sql - scope = all.relevant - builds = scope.select('count(*)').to_sql - success = scope.success.select('count(*)').to_sql - ignored = scope.ignored.select('count(*)').to_sql if scope.respond_to?(:ignored) - ignored ||= '0' - pending = scope.pending.select('count(*)').to_sql - running = scope.running.select('count(*)').to_sql - canceled = scope.canceled.select('count(*)').to_sql - skipped = scope.skipped.select('count(*)').to_sql - - deduce_status = "(CASE - WHEN (#{builds})=0 THEN NULL - WHEN (#{builds})=(#{skipped}) THEN 'skipped' - WHEN (#{builds})=(#{success})+(#{ignored})+(#{skipped}) THEN 'success' - WHEN (#{builds})=(#{pending})+(#{skipped}) THEN 'pending' - WHEN (#{builds})=(#{canceled})+(#{success})+(#{ignored})+(#{skipped}) THEN 'canceled' - WHEN (#{running})+(#{pending})>0 THEN 'running' - ELSE 'failed' - END)" - - deduce_status - end - - def status - all.pluck(self.status_sql).first - end - - def started_at - all.minimum(:started_at) - end - - def finished_at - all.maximum(:finished_at) - end - end - - included do - validates :status, inclusion: { in: AVAILABLE_STATUSES } - - state_machine :status, initial: :created do - state :created, value: 'created' - state :pending, value: 'pending' - state :running, value: 'running' - state :failed, value: 'failed' - state :success, value: 'success' - state :canceled, value: 'canceled' - state :skipped, value: 'skipped' - end - - scope :created, -> { where(status: 'created') } - scope :relevant, -> { where.not(status: 'created') } - scope :running, -> { where(status: 'running') } - scope :pending, -> { where(status: 'pending') } - scope :success, -> { where(status: 'success') } - scope :failed, -> { where(status: 'failed') } - scope :canceled, -> { where(status: 'canceled') } - scope :skipped, -> { where(status: 'skipped') } - scope :running_or_pending, -> { where(status: [:running, :pending]) } - scope :finished, -> { where(status: [:success, :failed, :canceled]) } - end - - def started? - STARTED_STATUSES.include?(status) && started_at - end - - def active? - ACTIVE_STATUSES.include?(status) - end - - def complete? - COMPLETED_STATUSES.include?(status) - end - - private - - def calculate_duration - if started_at && finished_at - finished_at - started_at - elsif started_at - Time.now - started_at - end - end -end diff --git a/app/services/ci/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb index 6f7610d42ba..f049ed628db 100644 --- a/app/services/ci/process_pipeline_service.rb +++ b/app/services/ci/process_pipeline_service.rb @@ -34,7 +34,7 @@ module Ci end def process_build(build, current_status) - return false unless Statuseable::COMPLETED_STATUSES.include?(current_status) + return false unless HasStatus::COMPLETED_STATUSES.include?(current_status) if valid_statuses_for_when(build.when).include?(current_status) build.enqueue -- cgit v1.2.1 From 33694a5a6465785c2fcd5c8217197070cbd7b316 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Tue, 2 Aug 2016 10:16:41 -0500 Subject: use gitlab global root url as canonical base url for all javascript set cookies (closes #20435) --- app/assets/javascripts/activities.js | 2 +- app/assets/javascripts/application.js | 4 ++-- app/assets/javascripts/awards_handler.js | 1 + app/assets/javascripts/project.js | 8 ++------ app/assets/javascripts/right_sidebar.js | 2 +- app/assets/javascripts/user.js | 4 +--- 6 files changed, 8 insertions(+), 13 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js index 1ab3c2197d8..5ea6086ab77 100644 --- a/app/assets/javascripts/activities.js +++ b/app/assets/javascripts/activities.js @@ -26,7 +26,7 @@ event_filters = $.cookie("event_filter"); filter = sender.attr("id").split("_")[0]; $.cookie("event_filter", (event_filters !== filter ? filter : ""), { - path: '/' + path: gon.relative_url_root || '/' }); if (event_filters !== filter) { return sender.closest('li').toggleClass("active"); diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index fc354dfd677..43a679501a7 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -288,7 +288,7 @@ new Aside(); if ($window.width() < 1024 && $.cookie('pin_nav') === 'true') { $.cookie('pin_nav', 'false', { - path: '/', + path: gon.relative_url_root || '/', expires: 365 * 10 }); $('.page-with-sidebar').toggleClass('page-sidebar-collapsed page-sidebar-expanded').removeClass('page-sidebar-pinned'); @@ -313,7 +313,7 @@ $topNav.removeClass('header-pinned-nav').toggleClass('header-collapsed header-expanded'); } $.cookie('pin_nav', doPinNav, { - path: '/', + path: gon.relative_url_root || '/', expires: 365 * 10 }); if ($.cookie('pin_nav') === 'true' || doPinNav) { diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index aee1c29eee3..ad12cb906e1 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -320,6 +320,7 @@ frequentlyUsedEmojis = this.getFrequentlyUsedEmojis(); frequentlyUsedEmojis.push(emoji); return $.cookie('frequently_used_emojis', frequentlyUsedEmojis.join(','), { + path: gon.relative_url_root || '/', expires: 365 }); }; diff --git a/app/assets/javascripts/project.js b/app/assets/javascripts/project.js index 4e1de4dfb72..66e097c0a28 100644 --- a/app/assets/javascripts/project.js +++ b/app/assets/javascripts/project.js @@ -17,19 +17,15 @@ return $(this).parents('form').submit(); }); $('.hide-no-ssh-message').on('click', function(e) { - var path; - path = '/'; $.cookie('hide_no_ssh_message', 'false', { - path: path + path: gon.relative_url_root || '/' }); $(this).parents('.no-ssh-key-message').remove(); return e.preventDefault(); }); $('.hide-no-password-message').on('click', function(e) { - var path; - path = '/'; $.cookie('hide_no_password_message', 'false', { - path: path + path: gon.relative_url_root || '/' }); $(this).parents('.no-password-message').remove(); return e.preventDefault(); diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js index dc4d5113826..e3d5f413c77 100644 --- a/app/assets/javascripts/right_sidebar.js +++ b/app/assets/javascripts/right_sidebar.js @@ -30,7 +30,7 @@ } if (!triggered) { return $.cookie("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed'), { - path: '/' + path: gon.relative_url_root || '/' }); } }); diff --git a/app/assets/javascripts/user.js b/app/assets/javascripts/user.js index b46390ad8f4..6c4d88cf407 100644 --- a/app/assets/javascripts/user.js +++ b/app/assets/javascripts/user.js @@ -7,10 +7,8 @@ }); this.initTabs(); $('.hide-project-limit-message').on('click', function(e) { - var path; - path = '/'; $.cookie('hide_project_limit_message', 'false', { - path: path + path: gon.relative_url_root || '/' }); $(this).parents('.project-limit-message').remove(); return e.preventDefault(); -- cgit v1.2.1 From 96051549672084fabec9f67b1cf03c59e8ac3370 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Sun, 31 Jul 2016 20:17:19 -0500 Subject: Automatically expand hidden discussions when accessed via a permalink hash (closes #19304) --- .../javascripts/behaviors/toggler_behavior.js | 30 +++++++++++++++++----- app/assets/javascripts/lib/utils/url_utility.js | 12 ++++++++- 2 files changed, 34 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/behaviors/toggler_behavior.js b/app/assets/javascripts/behaviors/toggler_behavior.js index 1b7b63489ea..8ac1ba7665e 100644 --- a/app/assets/javascripts/behaviors/toggler_behavior.js +++ b/app/assets/javascripts/behaviors/toggler_behavior.js @@ -1,10 +1,26 @@ -(function() { +(function(w) { $(function() { - return $("body").on("click", ".js-toggle-button", function(e) { - $(this).find('i').toggleClass('fa fa-chevron-down').toggleClass('fa fa-chevron-up'); - $(this).closest(".js-toggle-container").find(".js-toggle-content").toggle(); - return e.preventDefault(); + $('.js-toggle-button').on('click', function(e) { + e.preventDefault(); + $(this) + .find('.fa') + .toggleClass('fa-chevron-down fa-chevron-up') + .end() + .closest('.js-toggle-container') + .find('.js-toggle-content') + .toggle() + ; }); - }); -}).call(this); + // If we're accessing a permalink, ensure it is not inside a + // closed js-toggle-container! + var hash = w.gl.utils.getLocationHash(); + var anchor = hash && document.getElementById(hash); + var container = anchor && $(anchor).closest('.js-toggle-container'); + + if (container && container.find('.js-toggle-content').is(':hidden')) { + container.find('.js-toggle-button').trigger('click'); + anchor.scrollIntoView(); + } + }); +})(window); diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js index fffbfd19745..533310cc87c 100644 --- a/app/assets/javascripts/lib/utils/url_utility.js +++ b/app/assets/javascripts/lib/utils/url_utility.js @@ -43,7 +43,7 @@ } return newUrl; }; - return w.gl.utils.removeParamQueryString = function(url, param) { + w.gl.utils.removeParamQueryString = function(url, param) { var urlVariables, variables; url = decodeURIComponent(url); urlVariables = url.split('&'); @@ -59,6 +59,16 @@ return results; })()).join('&'); }; + w.gl.utils.getLocationHash = function(url) { + var hashIndex; + if (typeof url === 'undefined') { + // Note: We can't use window.location.hash here because it's + // not consistent across browsers - Firefox will pre-decode it + url = window.location.href; + } + hashIndex = url.indexOf('#'); + return hashIndex === -1 ? null : url.substring(hashIndex + 1); + }; })(window); }).call(this); -- cgit v1.2.1 From f8a7430b00cfe410b0274b8963f0de017ef098ee Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Wed, 24 Aug 2016 23:13:38 -0500 Subject: Fix unnecessary horizontal scroll area in pipeline visualizations --- app/assets/stylesheets/pages/pipelines.scss | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 6fa097e3bf1..7eb4e7ec676 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -265,7 +265,6 @@ .pipeline-visualization { position: relative; - min-width: 1220px; ul { padding: 0; -- cgit v1.2.1 From 7629dc9982f5559972acf9d9b9d98f78ad53e54c Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Fri, 12 Aug 2016 17:38:09 +0200 Subject: Add specs to ensure a successful return on the UI when mark as done a already done todo. --- app/services/todo_service.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb index e0ccb654590..2aab8c736d6 100644 --- a/app/services/todo_service.rb +++ b/app/services/todo_service.rb @@ -148,7 +148,8 @@ class TodoService def mark_todos_as_done_by_ids(ids, current_user) todos = current_user.todos.where(id: ids) - marked_todos = todos.update_all(state: :done) + # Only return those that are not really on that state + marked_todos = todos.where.not(state: :done).update_all(state: :done) current_user.update_todos_count_cache marked_todos end -- cgit v1.2.1 From dd8afbf05d0727a061e8d7bc1bc3c1db5a666116 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 25 Aug 2016 15:04:15 +0800 Subject: Just use instance variable instead, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_14400736 --- app/controllers/projects/artifacts_controller.rb | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 17c6d56c8b9..4c63bec90e5 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -37,8 +37,7 @@ class Projects::ArtifactsController < Projects::ApplicationController end def latest_succeeded - path = ref_name_and_path.last - target_path = artifacts_action_path(path, project, build) + target_path = artifacts_action_path(@path, project, build) if target_path redirect_to(target_path) @@ -63,17 +62,13 @@ class Projects::ArtifactsController < Projects::ApplicationController def build_from_ref if params[:ref_name_and_path] - ref_name = ref_name_and_path.first + ref_name, @path = extract_ref(params[:ref_name_and_path]) builds = project.latest_successful_builds_for(ref_name) builds.find_by(name: params[:job]) end end - def ref_name_and_path - @ref_name_and_path ||= extract_ref(params[:ref_name_and_path]) - end - def artifacts_file @artifacts_file ||= build.artifacts_file end -- cgit v1.2.1 From 085e1f89f327ad4d679696fe4673d09e1840b236 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Wed, 24 Aug 2016 18:06:19 +0100 Subject: Handle unavailable system info For Linux with the grsecurity patches applied, paths in `/proc` may not be readable, so handle those cases and show a message rather than blowing up. --- app/controllers/admin/system_info_controller.rb | 8 ++------ app/views/admin/system_info/show.html.haml | 12 ++++++++++-- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/controllers/admin/system_info_controller.rb b/app/controllers/admin/system_info_controller.rb index e4c73008826..ca04a17caa1 100644 --- a/app/controllers/admin/system_info_controller.rb +++ b/app/controllers/admin/system_info_controller.rb @@ -29,7 +29,8 @@ class Admin::SystemInfoController < Admin::ApplicationController ] def show - system_info = Vmstat.snapshot + @cpus = Vmstat.cpu rescue nil + @memory = Vmstat.memory rescue nil mounts = Sys::Filesystem.mounts @disks = [] @@ -50,10 +51,5 @@ class Admin::SystemInfoController < Admin::ApplicationController rescue Sys::Filesystem::Error end end - - @cpus = system_info.cpus.length - - @mem_used = system_info.memory.active_bytes - @mem_total = system_info.memory.total_bytes end end diff --git a/app/views/admin/system_info/show.html.haml b/app/views/admin/system_info/show.html.haml index 6956e5ab795..7f3b95699db 100644 --- a/app/views/admin/system_info/show.html.haml +++ b/app/views/admin/system_info/show.html.haml @@ -9,12 +9,20 @@ .light-well %h4 CPU .data - %h1= "#{@cpus} cores" + - if @cpus + %h1= "#{@cpus.length} cores" + - else + %i.fa.fa-warning.text-warning + Unable to collect CPU info .col-sm-4 .light-well %h4 Memory .data - %h1= "#{number_to_human_size(@mem_used)} / #{number_to_human_size(@mem_total)}" + - if @memory + %h1= "#{number_to_human_size(@memory.active_bytes)} / #{number_to_human_size(@memory.total_bytes)}" + - else + %i.fa.fa-warning.text-warning + Unable to collect memory info .col-sm-4 .light-well %h4 Disks -- cgit v1.2.1 From 6a2d2bd18d0a07c33200d74a09b7cf9adcb7a84d Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 25 Aug 2016 15:41:37 +0800 Subject: Add a download icon for artifacts, too. Feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_14400694 --- app/views/projects/buttons/_download.html.haml | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 73dcb9c079e..5f5e071eb40 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -38,4 +38,5 @@ - artifacts.each do |job| %li = link_to latest_succeeded_namespace_project_artifacts_path(project.namespace, project, ref, 'download', job: job.name), rel: 'nofollow' do + %i.fa.fa-download %span Download '#{job.name}' -- cgit v1.2.1 From d64c15c5c391e8f49a9f261ba0e59bafb99d97fe Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 25 Aug 2016 10:59:30 +0300 Subject: Add code improvements to merge request version feature * Add MergeRequestDiff#latest? * Remove unnecessary variable assignment Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/merge_requests_controller.rb | 2 +- app/models/merge_request_diff.rb | 16 ++++++++-------- .../projects/merge_requests/show/_versions.html.haml | 3 +-- 3 files changed, 10 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index eff959c781c..3be9bdb076d 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -93,7 +93,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController respond_to do |format| format.html { define_discussion_vars } format.json do - if @merge_request_diff != @merge_request.merge_request_diff + unless @merge_request_diff.latest? # Disable comments if browsing older version of the diff @diff_notes_disabled = true end diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index 42ab6b620bd..e353bdb24b8 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -79,14 +79,10 @@ class MergeRequestDiff < ActiveRecord::Base def raw_diffs(options = {}) if options[:ignore_whitespace_change] @diffs_no_whitespace ||= - begin - compare = Gitlab::Git::Compare.new( - repository.raw_repository, - safe_start_commit_sha, - safe_head_commit_sha - ) - compare.diffs(options) - end + Gitlab::Git::Compare.new( + repository.raw_repository, + safe_start_commit_sha, + safe_head_commit_sha).diffs(options) else @raw_diffs ||= {} @raw_diffs[options] ||= load_diffs(st_diffs, options) @@ -164,6 +160,10 @@ class MergeRequestDiff < ActiveRecord::Base end end + def latest? + self == merge_request.merge_request_diff + end + private def dump_commits(commits) diff --git a/app/views/projects/merge_requests/show/_versions.html.haml b/app/views/projects/merge_requests/show/_versions.html.haml index 15d94b16ced..08c54f0aeff 100644 --- a/app/views/projects/merge_requests/show/_versions.html.haml +++ b/app/views/projects/merge_requests/show/_versions.html.haml @@ -1,5 +1,4 @@ - merge_request_diffs = @merge_request.merge_request_diffs.select_without_diff -- latest_diff = merge_request_diffs.first - if merge_request_diffs.size > 1 .mr-version-switch @@ -7,7 +6,7 @@ %span.dropdown.inline %a.btn-link.dropdown-toggle{ data: {toggle: :dropdown} } %strong.monospace< - - if latest_diff == @merge_request_diff + - if @merge_request_diff.latest? #{"latest"} - else #{@merge_request_diff.head_commit.short_id} -- cgit v1.2.1 From 70fe671c299513a43797dc1e7ab0e32f14503175 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 25 Aug 2016 11:16:03 +0300 Subject: Make it more obvious when the user isn't currently viewing the latest mr version Signed-off-by: Dmitriy Zaporozhets --- app/views/projects/merge_requests/show/_versions.html.haml | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/views/projects/merge_requests/show/_versions.html.haml b/app/views/projects/merge_requests/show/_versions.html.haml index 08c54f0aeff..2da70ce7137 100644 --- a/app/views/projects/merge_requests/show/_versions.html.haml +++ b/app/views/projects/merge_requests/show/_versions.html.haml @@ -22,6 +22,10 @@ #{number_with_delimiter(merge_request_diff.commits.count)} #{'commit'.pluralize(merge_request_diff.commits.count)}, = time_ago_with_tooltip(merge_request_diff.created_at) + - unless @merge_request_diff.latest? + %span.prepend-left-default + = icon('info-circle') + This version is not the latest one. Comments are disabled .pull-right %span.monospace #{@merge_request_diff.base_commit.short_id}..#{@merge_request_diff.head_commit.short_id} -- cgit v1.2.1 From a943ccf10ecf2af3331927cb83268fbc70f43634 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 25 Aug 2016 11:58:17 +0300 Subject: Change the way merge request diff compare works * remove ref fetch (we do it during creation anyway) * remove safe_head_commit_sha for diff compare (do not depend on the source branch) Signed-off-by: Dmitriy Zaporozhets --- app/models/merge_request_diff.rb | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'app') diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb index e353bdb24b8..445179a4487 100644 --- a/app/models/merge_request_diff.rb +++ b/app/models/merge_request_diff.rb @@ -65,13 +65,6 @@ class MergeRequestDiff < ActiveRecord::Base start_commit_sha || merge_request.target_branch_sha end - # This method will rely on repository branch sha - # in case head_commit_sha is nil. Its necesarry for old merge request diff - # created before version 8.4 to work - def safe_head_commit_sha - head_commit_sha || merge_request.source_branch_sha - end - def size real_size.presence || raw_diffs.size end @@ -82,7 +75,7 @@ class MergeRequestDiff < ActiveRecord::Base Gitlab::Git::Compare.new( repository.raw_repository, safe_start_commit_sha, - safe_head_commit_sha).diffs(options) + head_commit_sha).diffs(options) else @raw_diffs ||= {} @raw_diffs[options] ||= load_diffs(st_diffs, options) @@ -148,16 +141,11 @@ class MergeRequestDiff < ActiveRecord::Base def compare @compare ||= - begin - # Update ref for merge request - merge_request.fetch_ref - - Gitlab::Git::Compare.new( - repository.raw_repository, - safe_start_commit_sha, - safe_head_commit_sha - ) - end + Gitlab::Git::Compare.new( + repository.raw_repository, + safe_start_commit_sha, + head_commit_sha + ) end def latest? -- cgit v1.2.1 From 4c8e9a8d27c34fe97216e12d17782f982818fb5c Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Thu, 18 Aug 2016 15:00:20 +0200 Subject: Remove gitorious --- app/assets/stylesheets/pages/import.scss | 19 --------- app/controllers/application_controller.rb | 6 +-- app/controllers/import/gitorious_controller.rb | 47 ---------------------- app/models/application_setting.rb | 2 +- app/views/import/gitorious/status.html.haml | 54 -------------------------- app/views/projects/new.html.haml | 5 --- 6 files changed, 2 insertions(+), 131 deletions(-) delete mode 100644 app/controllers/import/gitorious_controller.rb delete mode 100644 app/views/import/gitorious/status.html.haml (limited to 'app') diff --git a/app/assets/stylesheets/pages/import.scss b/app/assets/stylesheets/pages/import.scss index 84cc35239f9..a4f76a9495a 100644 --- a/app/assets/stylesheets/pages/import.scss +++ b/app/assets/stylesheets/pages/import.scss @@ -1,22 +1,3 @@ -i.icon-gitorious { - display: inline-block; - background-position: 0 0; - background-size: contain; - background-repeat: no-repeat; -} - -i.icon-gitorious-small { - background-image: image-url('gitorious-logo-blue.png'); - width: 13px; - height: 13px; -} - -i.icon-gitorious-big { - background-image: image-url('gitorious-logo-black.png'); - width: 18px; - height: 18px; -} - .import-jobs-from-col, .import-jobs-to-col { width: 40%; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 70a2275592b..ebc2a4651ba 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -25,7 +25,7 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :exception helper_method :abilities, :can?, :current_application_settings - helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :gitorious_import_enabled?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?, :gitlab_project_import_enabled? + helper_method :import_sources_enabled?, :github_import_enabled?, :github_import_configured?, :gitlab_import_enabled?, :gitlab_import_configured?, :bitbucket_import_enabled?, :bitbucket_import_configured?, :google_code_import_enabled?, :fogbugz_import_enabled?, :git_import_enabled?, :gitlab_project_import_enabled? rescue_from Encoding::CompatibilityError do |exception| log_exception(exception) @@ -250,10 +250,6 @@ class ApplicationController < ActionController::Base Gitlab::OAuth::Provider.enabled?(:bitbucket) && Gitlab::BitbucketImport.public_key.present? end - def gitorious_import_enabled? - current_application_settings.import_sources.include?('gitorious') - end - def google_code_import_enabled? current_application_settings.import_sources.include?('google_code') end diff --git a/app/controllers/import/gitorious_controller.rb b/app/controllers/import/gitorious_controller.rb deleted file mode 100644 index a4c4ad23027..00000000000 --- a/app/controllers/import/gitorious_controller.rb +++ /dev/null @@ -1,47 +0,0 @@ -class Import::GitoriousController < Import::BaseController - before_action :verify_gitorious_import_enabled - - def new - redirect_to client.authorize_url(callback_import_gitorious_url) - end - - def callback - session[:gitorious_repos] = params[:repos] - redirect_to status_import_gitorious_path - end - - def status - @repos = client.repos - - @already_added_projects = current_user.created_projects.where(import_type: "gitorious") - already_added_projects_names = @already_added_projects.pluck(:import_source) - - @repos.reject! { |repo| already_added_projects_names.include? repo.full_name } - end - - def jobs - jobs = current_user.created_projects.where(import_type: "gitorious").to_json(only: [:id, :import_status]) - render json: jobs - end - - def create - @repo_id = params[:repo_id] - repo = client.repo(@repo_id) - @target_namespace = params[:new_namespace].presence || repo.namespace - @project_name = repo.name - - namespace = get_or_create_namespace || (render and return) - - @project = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, current_user).execute - end - - private - - def client - @client ||= Gitlab::GitoriousImport::Client.new(session[:gitorious_repos]) - end - - def verify_gitorious_import_enabled - render_404 unless gitorious_import_enabled? - end -end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index f0bcb2d7cda..246477ffe88 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -146,7 +146,7 @@ class ApplicationSetting < ActiveRecord::Base default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'], default_snippet_visibility: Settings.gitlab.default_projects_features['visibility_level'], domain_whitelist: Settings.gitlab['domain_whitelist'], - import_sources: %w[github bitbucket gitlab gitorious google_code fogbugz git gitlab_project], + import_sources: %w[github bitbucket gitlab google_code fogbugz git gitlab_project], shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'], max_artifacts_size: Settings.artifacts['max_size'], require_two_factor_authentication: false, diff --git a/app/views/import/gitorious/status.html.haml b/app/views/import/gitorious/status.html.haml deleted file mode 100644 index ed3afb0ce33..00000000000 --- a/app/views/import/gitorious/status.html.haml +++ /dev/null @@ -1,54 +0,0 @@ -- page_title "Gitorious import" -- header_title "Projects", root_path -%h3.page-title - %i.icon-gitorious.icon-gitorious-big - Import projects from Gitorious.org - -%p.light - Select projects you want to import. -%hr -%p - = button_tag class: "btn btn-import btn-success js-import-all" do - Import all projects - = icon("spinner spin", class: "loading-icon") - -.table-responsive - %table.table.import-jobs - %colgroup.import-jobs-from-col - %colgroup.import-jobs-to-col - %colgroup.import-jobs-status-col - %thead - %tr - %th From Gitorious.org - %th To GitLab - %th Status - %tbody - - @already_added_projects.each do |project| - %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} - %td - = link_to project.import_source, "https://gitorious.org/#{project.import_source}", target: "_blank" - %td - = link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project] - %td.job-status - - if project.import_status == 'finished' - %span - %i.fa.fa-check - done - - elsif project.import_status == 'started' - %i.fa.fa-spinner.fa-spin - started - - else - = project.human_import_status_name - - - @repos.each do |repo| - %tr{id: "repo_#{repo.id}"} - %td - = link_to repo.full_name, "https://gitorious.org/#{repo.full_name}", target: "_blank" - %td.import-target - = repo.full_name - %td.import-actions.job-status - = button_tag class: "btn btn-import js-add-to-import" do - Import - = icon("spinner spin", class: "loading-icon") - -.js-importer-status{ data: { jobs_import_path: "#{jobs_import_gitorious_path}", import_path: "#{import_gitorious_path}" } } diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index ea4898f2107..0a1e2bb2cc6 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -59,11 +59,6 @@ = icon('gitlab', text: 'GitLab.com') - unless gitlab_import_configured? = render 'gitlab_import_modal' - %div - - if gitorious_import_enabled? - = link_to new_import_gitorious_path, class: 'btn import_gitorious' do - %i.icon-gitorious.icon-gitorious-small - Gitorious.org %div - if google_code_import_enabled? = link_to new_import_google_code_path, class: 'btn import_google_code' do -- cgit v1.2.1 From 4a3d1a5838685ff95a6c9416bb3e453ad143f50d Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Wed, 24 Aug 2016 15:20:06 +0100 Subject: Handle case where conflicts aren't on disk yet --- app/models/merge_request.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 5330a07ee35..7fa52d0b7a7 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -778,7 +778,7 @@ class MergeRequest < ActiveRecord::Base begin @conflicts_can_be_resolved_in_ui = conflicts.files.each(&:lines) - rescue Gitlab::Conflict::Parser::ParserError, Gitlab::Conflict::FileCollection::ConflictSideMissing + rescue Rugged::OdbError, Gitlab::Conflict::Parser::ParserError, Gitlab::Conflict::FileCollection::ConflictSideMissing @conflicts_can_be_resolved_in_ui = false end end -- cgit v1.2.1 From 67beaf6fb989e4f7981769b1f01bf383fc0de652 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 25 Aug 2016 12:32:35 +0100 Subject: Don't show conflicts when there are none --- app/models/merge_request.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 7fa52d0b7a7..19a684d1d0c 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -777,7 +777,11 @@ class MergeRequest < ActiveRecord::Base return @conflicts_can_be_resolved_in_ui = false unless has_complete_diff_refs? begin - @conflicts_can_be_resolved_in_ui = conflicts.files.each(&:lines) + # Try to parse each conflict. If the MR's mergeable status hasn't been updated, + # ensure that we don't say there are conflicts to resolve when there are no conflict + # files. + conflicts.files.each(&:lines) + @conflicts_can_be_resolved_in_ui = conflicts.files.length > 0 rescue Rugged::OdbError, Gitlab::Conflict::Parser::ParserError, Gitlab::Conflict::FileCollection::ConflictSideMissing @conflicts_can_be_resolved_in_ui = false end -- cgit v1.2.1 From 3bfb94b7593c3e14fa974701d733d6dc3c744bd2 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 24 Aug 2016 14:57:57 -0300 Subject: Label list shows all issues (opened or closed) with that label --- app/services/boards/issues/list_service.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb index 435a8c6e681..34efd09ed9f 100644 --- a/app/services/boards/issues/list_service.rb +++ b/app/services/boards/issues/list_service.rb @@ -36,7 +36,12 @@ module Boards end def set_state - params[:state] = list.done? ? 'closed' : 'opened' + params[:state] = + case list.list_type.to_sym + when :backlog then 'opened' + when :done then 'closed' + else 'all' + end end def board_label_ids -- cgit v1.2.1 From 6280fd3777920670ee42111fddf29576cbf85988 Mon Sep 17 00:00:00 2001 From: Paco Guzman Date: Tue, 23 Aug 2016 11:27:22 +0200 Subject: Reduce number of database queries on builds tab --- app/models/ci/build.rb | 2 +- app/models/ci/pipeline.rb | 2 +- app/models/commit_status.rb | 2 ++ app/views/projects/commit/_ci_stage.html.haml | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 096b3b801af..23c8de6f650 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -352,7 +352,7 @@ module Ci end def artifacts? - !artifacts_expired? && artifacts_file.exists? + !artifacts_expired? && self[:artifacts_file].present? end def artifacts_metadata? diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 087abe4cbb1..aff908ea16c 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -83,7 +83,7 @@ module Ci end def stages_with_latest_statuses - statuses.latest.order(:stage_idx).group_by(&:stage) + statuses.latest.includes(project: :namespace).order(:stage_idx).group_by(&:stage) end def project_id diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 84ceeac7d3e..1b403fa646d 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -25,6 +25,8 @@ class CommitStatus < ActiveRecord::Base scope :retried, -> { where.not(id: latest) } scope :ordered, -> { order(:name) } scope :ignored, -> { where(allow_failure: true, status: [:failed, :canceled]) } + scope :latest_ci_stages, -> { latest.ordered.includes(project: :namespace) } + scope :retried_ci_stages, -> { retried.ordered.includes(project: :namespace) } state_machine :status do event :enqueue do diff --git a/app/views/projects/commit/_ci_stage.html.haml b/app/views/projects/commit/_ci_stage.html.haml index 9d925cacc0d..6bb900e3fc1 100644 --- a/app/views/projects/commit/_ci_stage.html.haml +++ b/app/views/projects/commit/_ci_stage.html.haml @@ -8,8 +8,8 @@ - if stage   = stage.titleize - = render statuses.latest.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, allow_retry: true - = render statuses.retried.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, retried: true + = render statuses.latest_ci_stages, coverage: @project.build_coverage_enabled?, stage: false, ref: false, allow_retry: true + = render statuses.retried_ci_stages, coverage: @project.build_coverage_enabled?, stage: false, ref: false, retried: true %tr %td{colspan: 10}   -- cgit v1.2.1 From 79fd77953005062bfd89161770d1c0166774bb3d Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 25 Aug 2016 13:46:59 +0100 Subject: Allow setting branch refs for MR --- app/models/merge_request.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 5330a07ee35..918be8b7e66 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -238,12 +238,12 @@ class MergeRequest < ActiveRecord::Base def source_branch_head source_branch_ref = @source_branch_sha || source_branch - source_project.repository.commit(source_branch) if source_branch_ref + source_project.repository.commit(source_branch_ref) if source_branch_ref end def target_branch_head target_branch_ref = @target_branch_sha || target_branch - target_project.repository.commit(target_branch) if target_branch_ref + target_project.repository.commit(target_branch_ref) if target_branch_ref end def target_branch_sha -- cgit v1.2.1 From f16eabfc3335119015302798cb270445ddc0dc89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Rosen=C3=B6gger?= <123haynes@gmail.com> Date: Fri, 12 Aug 2016 16:29:13 +0200 Subject: Display project icon from default branch This commit makes sure that the project icon is being read from the default branch instead of 'master' --- app/controllers/projects/avatars_controller.rb | 2 +- app/models/project.rb | 1 + app/models/repository.rb | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb index 5962f74c39b..ada7db3c552 100644 --- a/app/controllers/projects/avatars_controller.rb +++ b/app/controllers/projects/avatars_controller.rb @@ -4,7 +4,7 @@ class Projects::AvatarsController < Projects::ApplicationController before_action :authorize_admin_project!, only: [:destroy] def show - @blob = @repository.blob_at_branch('master', @project.avatar_in_git) + @blob = @repository.blob_at_branch(@repository.root_ref, @project.avatar_in_git) if @blob headers['X-Content-Type-Options'] = 'nosniff' diff --git a/app/models/project.rb b/app/models/project.rb index 8cf093be4c3..0e4fb94f8eb 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1035,6 +1035,7 @@ class Project < ActiveRecord::Base "refs/heads/#{branch}", force: true) repository.copy_gitattributes(branch) + repository.expire_avatar_cache(branch) reload_default_branch end diff --git a/app/models/repository.rb b/app/models/repository.rb index bdc3b9d1c1c..91bdafdac99 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1065,7 +1065,7 @@ class Repository @avatar ||= cache.fetch(:avatar) do AVATAR_FILES.find do |file| - blob_at_branch('master', file) + blob_at_branch(root_ref, file) end end end -- cgit v1.2.1 From 77c22e95563f09e1430ac4fafcea4540463e3939 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 9 Aug 2016 14:44:43 -0500 Subject: Add font color contrast to external label in admin area --- app/assets/stylesheets/framework/nav.scss | 6 +----- app/assets/stylesheets/pages/admin.scss | 4 ++++ 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 9e924f99e9c..c72db86d958 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -71,7 +71,7 @@ .badge { font-weight: normal; background-color: #eee; - color: #78a; + color: $btn-transparent-color; vertical-align: baseline; } } @@ -335,10 +335,6 @@ } } - .badge { - color: $gl-icon-color; - } - &:hover { a, i { color: $black; diff --git a/app/assets/stylesheets/pages/admin.scss b/app/assets/stylesheets/pages/admin.scss index c9cdfdcd29c..8f71381f5c4 100644 --- a/app/assets/stylesheets/pages/admin.scss +++ b/app/assets/stylesheets/pages/admin.scss @@ -96,6 +96,10 @@ line-height: inherit; } } + + .label-default { + color: $btn-transparent-color; + } } .abuse-reports { -- cgit v1.2.1 From 5ab8977f183f15d3c638f5dfcfb2ac484c862124 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 25 Aug 2016 09:53:42 -0500 Subject: Fix inline emoji text alignment --- app/assets/stylesheets/framework/common.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index c1e5305644b..8984bce616c 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -248,7 +248,7 @@ li.note { img.emoji { height: 20px; - vertical-align: middle; + vertical-align: top; width: 20px; } -- cgit v1.2.1 From fc3dfb61b7f0dd7975f04cc068ff3e26c3a8b947 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Thu, 25 Aug 2016 16:07:20 +0100 Subject: Use icon helper --- app/views/admin/system_info/show.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/admin/system_info/show.html.haml b/app/views/admin/system_info/show.html.haml index 7f3b95699db..bfc6142067a 100644 --- a/app/views/admin/system_info/show.html.haml +++ b/app/views/admin/system_info/show.html.haml @@ -12,7 +12,7 @@ - if @cpus %h1= "#{@cpus.length} cores" - else - %i.fa.fa-warning.text-warning + = icon('warning', class: 'text-warning') Unable to collect CPU info .col-sm-4 .light-well @@ -21,7 +21,7 @@ - if @memory %h1= "#{number_to_human_size(@memory.active_bytes)} / #{number_to_human_size(@memory.total_bytes)}" - else - %i.fa.fa-warning.text-warning + = icon('warning', class: 'text-warning') Unable to collect memory info .col-sm-4 .light-well -- cgit v1.2.1 From fa3ec9d44aa13adf170b45c882f0ad6698f7f7f0 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 23 Aug 2016 11:14:06 -0500 Subject: Fix groups sort dropdown alignment --- app/views/explore/groups/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml index 57f6e7e0612..b8248a80a27 100644 --- a/app/views/explore/groups/index.html.haml +++ b/app/views/explore/groups/index.html.haml @@ -24,7 +24,7 @@ - else = sort_title_recently_created %b.caret - %ul.dropdown-menu + %ul.dropdown-menu.dropdown-menu-align-right %li = link_to explore_groups_path(sort: sort_value_recently_created) do = sort_title_recently_created -- cgit v1.2.1 From 77abf8cccfff01fa09a4014aea0f5afc309a7ca2 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 25 Aug 2016 10:47:40 -0500 Subject: Capitalize mentioned issue timeline notes --- app/services/system_note_service.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb index 546a8f11330..0c8446e7c3d 100644 --- a/app/services/system_note_service.rb +++ b/app/services/system_note_service.rb @@ -269,11 +269,11 @@ module SystemNoteService # # Example Note text: # - # "mentioned in #1" + # "Mentioned in #1" # - # "mentioned in !2" + # "Mentioned in !2" # - # "mentioned in 54f7727c" + # "Mentioned in 54f7727c" # # See cross_reference_note_content. # @@ -308,7 +308,7 @@ module SystemNoteService # Check if a cross-reference is disallowed # - # This method prevents adding a "mentioned in !1" note on every single commit + # This method prevents adding a "Mentioned in !1" note on every single commit # in a merge request. Additionally, it prevents the creation of references to # external issues (which would fail). # @@ -417,7 +417,7 @@ module SystemNoteService end def cross_reference_note_prefix - 'mentioned in ' + 'Mentioned in ' end def cross_reference_note_content(gfm_reference) -- cgit v1.2.1 From 82302b04fc53446a01fe1f36da261345415dca91 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 4 Aug 2016 10:53:05 -0500 Subject: Add hover color to emoji icon --- app/assets/stylesheets/pages/notes.scss | 16 +++++----------- app/views/projects/notes/_note.html.haml | 4 ++-- 2 files changed, 7 insertions(+), 13 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 08d1692c888..54124a3d658 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -281,19 +281,13 @@ ul.notes { font-size: 17px; } - &.js-note-delete { - i { - &:hover { - color: $gl-text-red; - } + &:hover { + .danger-highlight { + color: $gl-text-red; } - } - &.js-note-edit { - i { - &:hover { - color: $gl-link-color; - } + .link-highlight { + color: $gl-link-color; } } } diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml index d2ac1ce2b9a..7c82177f9ea 100644 --- a/app/views/projects/notes/_note.html.haml +++ b/app/views/projects/notes/_note.html.haml @@ -52,11 +52,11 @@ - if note.emoji_awardable? = link_to '#', title: 'Award Emoji', class: 'note-action-button note-emoji-button js-add-award js-note-emoji', data: { position: 'right' } do = icon('spinner spin') - = icon('smile-o') + = icon('smile-o', class: 'link-highlight') - if note_editable = link_to '#', title: 'Edit comment', class: 'note-action-button js-note-edit' do - = icon('pencil') + = icon('pencil', class: 'link-highlight') = link_to namespace_project_note_path(note.project.namespace, note.project, note), title: 'Remove comment', method: :delete, data: { confirm: 'Are you sure you want to remove this comment?' }, remote: true, class: 'note-action-button hidden-xs js-note-delete danger' do = icon('trash-o') .note-body{class: note_editable ? 'js-task-list-container' : ''} -- cgit v1.2.1 From a15e9f02b81f26cc07536d1458a576aede861529 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 11 Aug 2016 15:47:03 -0500 Subject: Reduce contributions calendar data payload --- .../javascripts/lib/utils/datetime_utility.js | 8 ++++ app/assets/javascripts/users/calendar.js | 51 +++++++++++++--------- 2 files changed, 38 insertions(+), 21 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index 10afa7e4329..d4d5927d3b0 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -67,6 +67,14 @@ $.timeago.settings.strings = tmpLocale; }; + w.gl.utils.getDayDifference = function(a, b) { + var millisecondsPerDay = 1000 * 60 * 60 * 24; + var date1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate()); + var date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate()); + + return Math.floor((date2 - date1) / millisecondsPerDay); + } + })(window); }).call(this); diff --git a/app/assets/javascripts/users/calendar.js b/app/assets/javascripts/users/calendar.js index 8b3dbf5f5ae..74ecf4f4cf9 100644 --- a/app/assets/javascripts/users/calendar.js +++ b/app/assets/javascripts/users/calendar.js @@ -3,7 +3,6 @@ this.Calendar = (function() { function Calendar(timestamps, calendar_activities_path) { - var group, i; this.calendar_activities_path = calendar_activities_path; this.clickDay = bind(this.clickDay, this); this.currentSelectedDate = ''; @@ -13,26 +12,36 @@ this.monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; this.months = []; this.timestampsTmp = []; - i = 0; - group = 0; - _.each(timestamps, (function(_this) { - return function(count, date) { - var day, innerArray, newDate; - newDate = new Date(parseInt(date) * 1000); - day = newDate.getDay(); - if ((day === 0 && i !== 0) || i === 0) { - _this.timestampsTmp.push([]); - group++; - } - innerArray = _this.timestampsTmp[group - 1]; - innerArray.push({ - count: count, - date: newDate, - day: day - }); - return i++; - }; - })(this)); + var group = 0; + + var today = new Date() + today.setHours(0, 0, 0, 0, 0); + + var oneYearAgo = new Date(today); + oneYearAgo.setFullYear(today.getFullYear() - 1); + + var days = gl.utils.getDayDifference(oneYearAgo, today); + + for(var i = 0; i <= days; i++) { + var date = new Date(oneYearAgo); + date.setDate(date.getDate() + i); + + var day = date.getDay(); + var count = timestamps[date.getTime() * 0.001]; + + if ((day === 0 && i !== 0) || i === 0) { + this.timestampsTmp.push([]); + group++; + } + + var innerArray = this.timestampsTmp[group - 1]; + innerArray.push({ + count: count || 0, + date: date, + day: day + }); + } + this.colorKey = this.initColorKey(); this.color = this.initColor(); this.renderSvg(group); -- cgit v1.2.1 From ace38e8397bd4c3eca11e0aafe9a8682ad81bf45 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 24 Aug 2016 20:06:16 -0700 Subject: Fix external issue tracker "Issues" link leading to 404s a70431f874 modified the behavior to link to the external issue tracker issues URL instead of the project path URL. This restores the previous behavior. Closes #21252, #21402 --- app/controllers/projects/issues_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 7b0189150f8..7c03dcd2e64 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -212,7 +212,7 @@ class Projects::IssuesController < Projects::ApplicationController if action_name == 'new' redirect_to external.new_issue_path else - redirect_to external.issues_url + redirect_to external.project_path end end -- cgit v1.2.1 From 4d6dfeee1af07f6e8950ff73b30707d2a72fc938 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Wed, 10 Aug 2016 15:41:31 -0500 Subject: Add horizontal scrolling to all sub-navs on mobile viewports --- app/assets/stylesheets/framework/nav.scss | 20 ++++----- app/views/admin/background_jobs/_head.html.haml | 46 +++++++++++---------- app/views/admin/dashboard/_head.html.haml | 54 +++++++++++++------------ app/views/projects/commits/_head.html.haml | 5 +-- app/views/projects/graphs/_head.html.haml | 32 ++++++++------- app/views/projects/issues/_head.html.haml | 54 +++++++++++++------------ app/views/projects/pipelines/_head.html.haml | 36 +++++++++-------- app/views/projects/wikis/_nav.html.haml | 22 +++++----- app/views/shared/_nav_scroll.html.haml | 4 ++ 9 files changed, 144 insertions(+), 129 deletions(-) create mode 100644 app/views/shared/_nav_scroll.html.haml (limited to 'app') diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 9e924f99e9c..7854f419bc2 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -1,4 +1,4 @@ -@mixin fade($gradient-direction, $rgba, $gradient-color) { +@mixin fade($gradient-direction, $gradient-color) { visibility: hidden; opacity: 0; z-index: 2; @@ -8,10 +8,10 @@ height: 30px; transition-duration: .3s; -webkit-transform: translateZ(0); - background: -webkit-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); - background: -o-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); - background: -moz-linear-gradient($gradient-direction, $rgba, $gradient-color 45%); - background: linear-gradient($gradient-direction, $rgba, $gradient-color 45%); + background: -webkit-linear-gradient($gradient-direction, rgba($gradient-color, 0.4), $gradient-color 45%); + background: -o-linear-gradient($gradient-direction, rgba($gradient-color, 0.4), $gradient-color 45%); + background: -moz-linear-gradient($gradient-direction, rgba($gradient-color, 0.4), $gradient-color 45%); + background: linear-gradient($gradient-direction, rgba($gradient-color, 0.4), $gradient-color 45%); &.scrolling { visibility: visible; @@ -356,7 +356,7 @@ } .fade-right { - @include fade(left, rgba(255, 255, 255, 0.4), $background-color); + @include fade(left, $background-color); right: -5px; .fa { @@ -365,7 +365,7 @@ } .fade-left { - @include fade(right, rgba(255, 255, 255, 0.4), $background-color); + @include fade(right, $background-color); left: -5px; .fa { @@ -376,6 +376,7 @@ &.sub-nav-scroll { .fade-right { + @include fade(left, $dark-background-color); right: 0; .fa { @@ -384,6 +385,7 @@ } .fade-left { + @include fade(right, $dark-background-color); left: 0; .fa { @@ -400,7 +402,7 @@ @include scrolling-links(); .fade-right { - @include fade(left, rgba(255, 255, 255, 0.4), $white-light); + @include fade(left, $white-light); right: -5px; .fa { @@ -409,7 +411,7 @@ } .fade-left { - @include fade(right, rgba(255, 255, 255, 0.4), $white-light); + @include fade(right, $white-light); left: -5px; .fa { diff --git a/app/views/admin/background_jobs/_head.html.haml b/app/views/admin/background_jobs/_head.html.haml index 89d7a40d6b0..107fc25244a 100644 --- a/app/views/admin/background_jobs/_head.html.haml +++ b/app/views/admin/background_jobs/_head.html.haml @@ -1,22 +1,24 @@ -.nav-links.sub-nav - %ul{ class: (container_class) } - = nav_link(controller: :system_info) do - = link_to admin_system_info_path, title: 'System Info' do - %span - System Info - = nav_link(controller: :background_jobs) do - = link_to admin_background_jobs_path, title: 'Background Jobs' do - %span - Background Jobs - = nav_link(controller: :logs) do - = link_to admin_logs_path, title: 'Logs' do - %span - Logs - = nav_link(controller: :health_check) do - = link_to admin_health_check_path, title: 'Health Check' do - %span - Health Check - = nav_link(controller: :requests_profiles) do - = link_to admin_requests_profiles_path, title: 'Requests Profiles' do - %span - Requests Profiles +.scrolling-tabs-container.sub-nav-scroll + = render 'shared/nav_scroll' + .nav-links.sub-nav.scrolling-tabs + %ul{ class: (container_class) } + = nav_link(controller: :system_info) do + = link_to admin_system_info_path, title: 'System Info' do + %span + System Info + = nav_link(controller: :background_jobs) do + = link_to admin_background_jobs_path, title: 'Background Jobs' do + %span + Background Jobs + = nav_link(controller: :logs) do + = link_to admin_logs_path, title: 'Logs' do + %span + Logs + = nav_link(controller: :health_check) do + = link_to admin_health_check_path, title: 'Health Check' do + %span + Health Check + = nav_link(controller: :requests_profiles) do + = link_to admin_requests_profiles_path, title: 'Requests Profiles' do + %span + Requests Profiles diff --git a/app/views/admin/dashboard/_head.html.haml b/app/views/admin/dashboard/_head.html.haml index b74da64f82e..c91ab4cb946 100644 --- a/app/views/admin/dashboard/_head.html.haml +++ b/app/views/admin/dashboard/_head.html.haml @@ -1,26 +1,28 @@ -.nav-links.sub-nav - %ul{ class: (container_class) } - = nav_link(controller: :dashboard, html_options: {class: 'home'}) do - = link_to admin_root_path, title: 'Overview' do - %span - Overview - = nav_link(controller: [:admin, :projects]) do - = link_to admin_namespaces_projects_path, title: 'Projects' do - %span - Projects - = nav_link(controller: :users) do - = link_to admin_users_path, title: 'Users' do - %span - Users - = nav_link(controller: :groups) do - = link_to admin_groups_path, title: 'Groups' do - %span - Groups - = nav_link path: 'builds#index' do - = link_to admin_builds_path, title: 'Builds' do - %span - Builds - = nav_link path: ['runners#index', 'runners#show'] do - = link_to admin_runners_path, title: 'Runners' do - %span - Runners +.scrolling-tabs-container.sub-nav-scroll + = render 'shared/nav_scroll' + .nav-links.sub-nav.scrolling-tabs + %ul{ class: (container_class) } + = nav_link(controller: :dashboard, html_options: {class: 'home'}) do + = link_to admin_root_path, title: 'Overview' do + %span + Overview + = nav_link(controller: [:admin, :projects]) do + = link_to admin_namespaces_projects_path, title: 'Projects' do + %span + Projects + = nav_link(controller: :users) do + = link_to admin_users_path, title: 'Users' do + %span + Users + = nav_link(controller: :groups) do + = link_to admin_groups_path, title: 'Groups' do + %span + Groups + = nav_link path: 'builds#index' do + = link_to admin_builds_path, title: 'Builds' do + %span + Builds + = nav_link path: ['runners#index', 'runners#show'] do + = link_to admin_runners_path, title: 'Runners' do + %span + Runners diff --git a/app/views/projects/commits/_head.html.haml b/app/views/projects/commits/_head.html.haml index 61152649907..4d1ee1c5318 100644 --- a/app/views/projects/commits/_head.html.haml +++ b/app/views/projects/commits/_head.html.haml @@ -1,8 +1,5 @@ .scrolling-tabs-container.sub-nav-scroll - .fade-left - = icon('angle-left') - .fade-right - = icon('angle-right') + = render 'shared/nav_scroll' .nav-links.sub-nav.scrolling-tabs %ul{ class: (container_class) } = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do diff --git a/app/views/projects/graphs/_head.html.haml b/app/views/projects/graphs/_head.html.haml index 45e51389c00..a231d684559 100644 --- a/app/views/projects/graphs/_head.html.haml +++ b/app/views/projects/graphs/_head.html.haml @@ -1,16 +1,18 @@ -.nav-links.sub-nav - %ul{ class: (container_class) } +.scrolling-tabs-container.sub-nav-scroll + = render 'shared/nav_scroll' + .nav-links.sub-nav.scrolling-tabs + %ul{ class: (container_class) } - - content_for :page_specific_javascripts do - = page_specific_javascript_tag('lib/chart.js') - = page_specific_javascript_tag('graphs/graphs_bundle.js') - = nav_link(action: :show) do - = link_to 'Contributors', namespace_project_graph_path - = nav_link(action: :commits) do - = link_to 'Commits', commits_namespace_project_graph_path - = nav_link(action: :languages) do - = link_to 'Languages', languages_namespace_project_graph_path - - if @project.builds_enabled? - = nav_link(action: :ci) do - = link_to ci_namespace_project_graph_path do - Continuous Integration + - content_for :page_specific_javascripts do + = page_specific_javascript_tag('lib/chart.js') + = page_specific_javascript_tag('graphs/graphs_bundle.js') + = nav_link(action: :show) do + = link_to 'Contributors', namespace_project_graph_path + = nav_link(action: :commits) do + = link_to 'Commits', commits_namespace_project_graph_path + = nav_link(action: :languages) do + = link_to 'Languages', languages_namespace_project_graph_path + - if @project.builds_enabled? + = nav_link(action: :ci) do + = link_to ci_namespace_project_graph_path do + Continuous Integration diff --git a/app/views/projects/issues/_head.html.haml b/app/views/projects/issues/_head.html.haml index b6cb559afcb..f88b33018d0 100644 --- a/app/views/projects/issues/_head.html.haml +++ b/app/views/projects/issues/_head.html.haml @@ -1,30 +1,32 @@ -.nav-links.sub-nav - %ul{ class: (container_class) } - - if project_nav_tab?(:issues) && !current_controller?(:merge_requests) - = nav_link(controller: :issues) do - = link_to namespace_project_issues_path(@project.namespace, @project), title: 'Issues' do - %span - Issues +.scrolling-tabs-container.sub-nav-scroll + = render 'shared/nav_scroll' + .nav-links.sub-nav.scrolling-tabs + %ul{ class: (container_class) } + - if project_nav_tab?(:issues) && !current_controller?(:merge_requests) + = nav_link(controller: :issues) do + = link_to namespace_project_issues_path(@project.namespace, @project), title: 'Issues' do + %span + Issues - = nav_link(controller: :boards) do - = link_to namespace_project_board_path(@project.namespace, @project), title: 'Board' do - %span - Board + = nav_link(controller: :boards) do + = link_to namespace_project_board_path(@project.namespace, @project), title: 'Board' do + %span + Board - - if project_nav_tab?(:merge_requests) && current_controller?(:merge_requests) - = nav_link(controller: :merge_requests) do - = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests' do - %span - Merge Requests + - if project_nav_tab?(:merge_requests) && current_controller?(:merge_requests) + = nav_link(controller: :merge_requests) do + = link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests' do + %span + Merge Requests - - if project_nav_tab? :labels - = nav_link(controller: :labels) do - = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do - %span - Labels + - if project_nav_tab? :labels + = nav_link(controller: :labels) do + = link_to namespace_project_labels_path(@project.namespace, @project), title: 'Labels' do + %span + Labels - - if project_nav_tab? :milestones - = nav_link(controller: :milestones) do - = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do - %span - Milestones + - if project_nav_tab? :milestones + = nav_link(controller: :milestones) do + = link_to namespace_project_milestones_path(@project.namespace, @project), title: 'Milestones' do + %span + Milestones \ No newline at end of file diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml index d65faf86d4e..f611ddc8f5f 100644 --- a/app/views/projects/pipelines/_head.html.haml +++ b/app/views/projects/pipelines/_head.html.haml @@ -1,19 +1,21 @@ -.nav-links.sub-nav - %ul{ class: (container_class) } - - if project_nav_tab? :pipelines - = nav_link(controller: :pipelines) do - = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do - %span - Pipelines +.scrolling-tabs-container.sub-nav-scroll + = render 'shared/nav_scroll' + .nav-links.sub-nav.scrolling-tabs + %ul{ class: (container_class) } + - if project_nav_tab? :pipelines + = nav_link(controller: :pipelines) do + = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do + %span + Pipelines - - if project_nav_tab? :builds - = nav_link(controller: %w(builds)) do - = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do - %span - Builds + - if project_nav_tab? :builds + = nav_link(controller: %w(builds)) do + = link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds' do + %span + Builds - - if project_nav_tab? :environments - = nav_link(controller: %w(environments)) do - = link_to project_environments_path(@project), title: 'Environments', class: 'shortcuts-environments' do - %span - Environments + - if project_nav_tab? :environments + = nav_link(controller: %w(environments)) do + = link_to project_environments_path(@project), title: 'Environments', class: 'shortcuts-environments' do + %span + Environments diff --git a/app/views/projects/wikis/_nav.html.haml b/app/views/projects/wikis/_nav.html.haml index f8ea479e0b1..551a20c1044 100644 --- a/app/views/projects/wikis/_nav.html.haml +++ b/app/views/projects/wikis/_nav.html.haml @@ -1,13 +1,15 @@ -.nav-links.sub-nav - %ul{ class: (container_class) } - = nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do - = link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home) +.scrolling-tabs-container.sub-nav-scroll + = render 'shared/nav_scroll' + .nav-links.sub-nav.scrolling-tabs + %ul{ class: (container_class) } + = nav_link(html_options: {class: params[:id] == 'home' ? 'active' : '' }) do + = link_to 'Home', namespace_project_wiki_path(@project.namespace, @project, :home) - = nav_link(path: 'wikis#pages') do - = link_to 'Pages', namespace_project_wiki_pages_path(@project.namespace, @project) + = nav_link(path: 'wikis#pages') do + = link_to 'Pages', namespace_project_wiki_pages_path(@project.namespace, @project) - = nav_link(path: 'wikis#git_access') do - = link_to namespace_project_wikis_git_access_path(@project.namespace, @project) do - Git Access + = nav_link(path: 'wikis#git_access') do + = link_to namespace_project_wikis_git_access_path(@project.namespace, @project) do + Git Access - = render 'projects/wikis/new' + = render 'projects/wikis/new' diff --git a/app/views/shared/_nav_scroll.html.haml b/app/views/shared/_nav_scroll.html.haml new file mode 100644 index 00000000000..4e3b1b3a571 --- /dev/null +++ b/app/views/shared/_nav_scroll.html.haml @@ -0,0 +1,4 @@ +.fade-left + = icon('angle-left') +.fade-right + = icon('angle-right') \ No newline at end of file -- cgit v1.2.1 From 7ed0acd422a95c4cbb1406f67929a5da669f2681 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 4 Aug 2016 12:18:00 -0600 Subject: turned ES5 users.js to ES6 users.js.es6 for babel added semicolons remove users.js rename users to user in filename removed uneeded semi-colons and returning null in constructor class is wrapped - a lot of builds will fail formatting replaced 'new User' with 'new gl.User' in app/users/show.html.haml window.gl || window.gl = {} - seeing if rspec9/spinach6/spinach9 will pass putting window logic before IIFE Fixed typo in users show view - extracted jquery calls in constructor to prototype methods fixed window declaration in IIFE argument adding new line --- app/assets/javascripts/user.js | 29 ----------------------------- app/assets/javascripts/user.js.es6 | 35 +++++++++++++++++++++++++++++++++++ app/views/users/show.html.haml | 2 +- 3 files changed, 36 insertions(+), 30 deletions(-) delete mode 100644 app/assets/javascripts/user.js create mode 100644 app/assets/javascripts/user.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/user.js b/app/assets/javascripts/user.js deleted file mode 100644 index 6c4d88cf407..00000000000 --- a/app/assets/javascripts/user.js +++ /dev/null @@ -1,29 +0,0 @@ -(function() { - this.User = (function() { - function User(opts) { - this.opts = opts; - $('.profile-groups-avatars').tooltip({ - "placement": "top" - }); - this.initTabs(); - $('.hide-project-limit-message').on('click', function(e) { - $.cookie('hide_project_limit_message', 'false', { - path: gon.relative_url_root || '/' - }); - $(this).parents('.project-limit-message').remove(); - return e.preventDefault(); - }); - } - - User.prototype.initTabs = function() { - return new UserTabs({ - parentEl: '.user-profile', - action: this.opts.action - }); - }; - - return User; - - })(); - -}).call(this); diff --git a/app/assets/javascripts/user.js.es6 b/app/assets/javascripts/user.js.es6 new file mode 100644 index 00000000000..c934afa458a --- /dev/null +++ b/app/assets/javascripts/user.js.es6 @@ -0,0 +1,35 @@ +(global => { + global.User = class { + constructor(opts) { + this.opts = opts; + this.placeTop(); + this.initTabs(); + this.hideProjectLimitMessage(); + } + + placeTop() { + $('.profile-groups-avatars').tooltip({ + "placement": "top" + }); + } + + initTabs() { + return new UserTabs({ + parentEl: '.user-profile', + action: this.opts.action + }); + } + + hideProjectLimitMessage() { + $('.hide-project-limit-message').on('click', e => { + const path = '/'; + $.cookie('hide_project_limit_message', 'false', { + path: path + }); + $(this).parents('.project-limit-message').remove(); + e.preventDefault(); + return; + }); + } + } +})(window.gl || (window.gl = {})); diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index c7f39868e71..9a052abe40a 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -123,6 +123,6 @@ :javascript var userProfile; - userProfile = new User({ + userProfile = new gl.User({ action: "#{controller.action_name}" }); -- cgit v1.2.1 From f0866b28d384f569345eccb6e64ad93d29a3e570 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 25 Aug 2016 20:43:24 -0500 Subject: Fix repo title alignment --- app/assets/stylesheets/framework/header.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 0c607071840..41ffaa38f6c 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -94,7 +94,7 @@ header { .side-nav-toggle { position: absolute; left: -10px; - margin: 6px 0; + margin: 7px 0; font-size: 18px; padding: 6px 10px; border: none; -- cgit v1.2.1 From 0fe4cf2b0fdbc33572f11bba1a4426ee05ed7599 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 24 Aug 2016 20:06:16 -0700 Subject: Fix Sentry not reporting right program for Sidekiq workers Moves program tag into the global configuration since this doesn't change and since Sidekiq workers get a unique context for each event. Closes #21410 --- app/helpers/sentry_helper.rb | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) (limited to 'app') diff --git a/app/helpers/sentry_helper.rb b/app/helpers/sentry_helper.rb index f8cccade15b..3d255df66a0 100644 --- a/app/helpers/sentry_helper.rb +++ b/app/helpers/sentry_helper.rb @@ -1,27 +1,9 @@ module SentryHelper def sentry_enabled? - Rails.env.production? && current_application_settings.sentry_enabled? + Gitlab::Sentry.enabled? end def sentry_context - return unless sentry_enabled? - - if current_user - Raven.user_context( - id: current_user.id, - email: current_user.email, - username: current_user.username, - ) - end - - Raven.tags_context(program: sentry_program_context) - end - - def sentry_program_context - if Sidekiq.server? - 'sidekiq' - else - 'rails' - end + Gitlab::Sentry.context(current_user) end end -- cgit v1.2.1 From 71d552029126b42de1191a68dd270b5491d849ea Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 11 Aug 2016 10:08:06 -0500 Subject: Fix branches page dropdown sort alignment --- app/assets/stylesheets/framework/nav.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss index 9e924f99e9c..ceafdc20ebc 100644 --- a/app/assets/stylesheets/framework/nav.scss +++ b/app/assets/stylesheets/framework/nav.scss @@ -161,6 +161,7 @@ > .dropdown { margin-right: $gl-padding-top; display: inline-block; + vertical-align: top; &:last-child { margin-right: 0; -- cgit v1.2.1 From b17df0507b704a347d6a8af035526b642ec85284 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Fri, 26 Aug 2016 13:10:03 +0800 Subject: Extract ref_name and path in before_action, feedback: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5142#note_14469768 --- app/controllers/projects/artifacts_controller.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 4c63bec90e5..59222637961 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -4,6 +4,7 @@ class Projects::ArtifactsController < Projects::ApplicationController layout 'project' before_action :authorize_read_build! before_action :authorize_update_build!, only: [:keep] + before_action :extract_ref_name_and_path before_action :validate_artifacts! def download @@ -48,6 +49,12 @@ class Projects::ArtifactsController < Projects::ApplicationController private + def extract_ref_name_and_path + return unless params[:ref_name_and_path] + + @ref_name, @path = extract_ref(params[:ref_name_and_path]) + end + def validate_artifacts! render_404 unless build && build.artifacts? end @@ -61,12 +68,10 @@ class Projects::ArtifactsController < Projects::ApplicationController end def build_from_ref - if params[:ref_name_and_path] - ref_name, @path = extract_ref(params[:ref_name_and_path]) - builds = project.latest_successful_builds_for(ref_name) + return unless @ref_name - builds.find_by(name: params[:job]) - end + builds = project.latest_successful_builds_for(@ref_name) + builds.find_by(name: params[:job]) end def artifacts_file -- cgit v1.2.1 From 1ca59776b03201f2337aaba7233e957f3597ca3b Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Wed, 24 Aug 2016 09:11:29 -0500 Subject: Fix enormous IE11 fork button --- app/assets/stylesheets/framework/buttons.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 6c3786b49bb..cd3ddf5fee9 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -200,7 +200,7 @@ svg { height: 15px; - width: auto; + width: 15px; position: relative; top: 2px; } -- cgit v1.2.1 From 770ecd55dd7fa483e440386a6635c2833c5239c1 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Thu, 25 Aug 2016 12:48:15 -0500 Subject: Curved lines at top of pipeline graph --- app/assets/stylesheets/pages/pipelines.scss | 46 +++++++++++++++++++++- .../projects/ci/builds/_build_pipeline.html.haml | 1 + 2 files changed, 45 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 9bdf0d250bb..9b7bf9575ff 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -370,8 +370,11 @@ // Connect second build to first build with smaller curved line &:nth-child(2) { &::after, &::before { - height: 45px; - top: -26px; + height: 29px; + top: -10px; + } + .curve { + display: block; } } } @@ -390,6 +393,12 @@ border: none; } } + // Remove opposite curve + .curve { + &::before { + display: none; + } + } } } @@ -401,6 +410,39 @@ border: none; } } + // Remove opposite curve + .curve { + &::after { + display: none; + } + } + } + } + + // Curve first child connecting lines in opposite direction + .curve { + display: none; + + &::before, + &::after { + content: ''; + width: 21px; + height: 25px; + position: absolute; + top: -28.5px; + border-top: 2px solid $border-color; + } + + &::after { + left: -39px; + border-right: 2px solid $border-color; + border-radius: 0 50% 0; + } + + &::before { + right: -39px; + border-left: 2px solid $border-color; + border-radius: 50% 0 0; } } } diff --git a/app/views/projects/ci/builds/_build_pipeline.html.haml b/app/views/projects/ci/builds/_build_pipeline.html.haml index 04cbd0c3591..ebdf60ae370 100644 --- a/app/views/projects/ci/builds/_build_pipeline.html.haml +++ b/app/views/projects/ci/builds/_build_pipeline.html.haml @@ -1,5 +1,6 @@ - is_playable = subject.playable? && can?(current_user, :update_build, @project) %li.build{class: ("playable" if is_playable)} + .curve .build-content - if is_playable = link_to play_namespace_project_build_path(subject.project.namespace, subject.project, subject, return_to: request.original_url), method: :post, title: 'Play' do -- cgit v1.2.1 From 906c14e31a8f58478aab2528ecb8d874404dfa16 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Thu, 25 Aug 2016 14:40:51 -0500 Subject: Scss lint fix --- app/assets/stylesheets/pages/pipelines.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 9b7bf9575ff..df8fc0ee154 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -436,7 +436,7 @@ &::after { left: -39px; border-right: 2px solid $border-color; - border-radius: 0 50% 0; + border-radius: 0 50%; } &::before { -- cgit v1.2.1 From a2be0e59e0cdb3de518740805266c719c6255f7b Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Fri, 26 Aug 2016 09:28:00 -0500 Subject: Unify border radiuses to 15px, move columns further apart --- app/assets/stylesheets/pages/pipelines.scss | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index df8fc0ee154..743fe89a9f4 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -273,7 +273,7 @@ .stage-column { display: inline-block; vertical-align: top; - margin-right: 50px; + margin-right: 65px; li { list-style: none; @@ -334,9 +334,9 @@ content: ''; position: absolute; top: 50%; - right: -54px; + right: -69px; border-top: 2px solid $border-color; - width: 54px; + width: 69px; height: 1px; } } @@ -356,14 +356,14 @@ &::after { right: -20px; border-right: 2px solid $border-color; - border-radius: 0 0 50px; + border-radius: 0 0 15px; } // Left connecting curves &::before { left: -20px; border-left: 2px solid $border-color; - border-radius: 0 0 0 50px; + border-radius: 0 0 0 15px; } } @@ -436,13 +436,13 @@ &::after { left: -39px; border-right: 2px solid $border-color; - border-radius: 0 50%; + border-radius: 0 15px; } &::before { right: -39px; border-left: 2px solid $border-color; - border-radius: 50% 0 0; + border-radius: 15px 0 0; } } } -- cgit v1.2.1 From aeb280b0ccb7186b75cf73fcd2e051c5ed661443 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 25 Aug 2016 09:19:14 -0500 Subject: Fix markdown help references --- app/helpers/search_helper.rb | 2 +- app/views/admin/appearances/_form.html.haml | 2 +- app/views/help/ui.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index c0195713f4a..4549c2e5bb6 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -44,7 +44,7 @@ module SearchHelper def help_autocomplete [ { category: "Help", label: "API Help", url: help_page_path("api/README") }, - { category: "Help", label: "Markdown Help", url: help_page_path("markdown/markdown") }, + { category: "Help", label: "Markdown Help", url: help_page_path("user/markdown") }, { category: "Help", label: "Permissions Help", url: help_page_path("user/permissions") }, { category: "Help", label: "Public Access Help", url: help_page_path("public_access/public_access") }, { category: "Help", label: "Rake Tasks Help", url: help_page_path("raketasks/README") }, diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml index 92e2dae4842..9175b3d3f96 100644 --- a/app/views/admin/appearances/_form.html.haml +++ b/app/views/admin/appearances/_form.html.haml @@ -13,7 +13,7 @@ .col-sm-10 = f.text_area :description, class: "form-control", rows: 10 .hint - Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('markdown/markdown'), target: '_blank'}. + Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('user/markdown'), target: '_blank'}. .form-group = f.label :logo, class: 'control-label' .col-sm-10 diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml index 85e188d6f8b..d16bd61b779 100644 --- a/app/views/help/ui.html.haml +++ b/app/views/help/ui.html.haml @@ -549,4 +549,4 @@ %li wiki page %li help page - You can check how markdown rendered at #{link_to 'Markdown help page', help_page_path("markdown/markdown")}. + You can check how markdown rendered at #{link_to 'Markdown help page', help_page_path("user/markdown")}. -- cgit v1.2.1 From 0e0d0ede2c265de4b2fdf76a1376cfced3efaacd Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 25 Aug 2016 12:42:22 -0500 Subject: Fix inconsistent checkbox alignment --- app/assets/stylesheets/pages/issues.scss | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index dfe1e3075da..3a3bb10feac 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -12,6 +12,10 @@ padding-right: 8px; margin-bottom: 10px; min-width: 15px; + + .selected_issue { + vertical-align: text-top; + } } .issue-labels { -- cgit v1.2.1 From 6686084c6502f10fd7e6b8963ab52526cb6831bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Rodr=C3=ADguez?= Date: Fri, 26 Aug 2016 17:20:00 -0300 Subject: Fix "Wiki" link not appearing in navigation for projects with external wiki --- app/models/ability.rb | 2 +- app/models/project.rb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/ability.rb b/app/models/ability.rb index a49dd703926..c1df4a865f6 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -355,7 +355,7 @@ class Ability rules += named_abilities('project_snippet') end - unless project.wiki_enabled + unless project.has_wiki? rules += named_abilities('wiki') end diff --git a/app/models/project.rb b/app/models/project.rb index 0e4fb94f8eb..0fa41ebbec3 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -680,6 +680,10 @@ class Project < ActiveRecord::Base update_column(:has_external_issue_tracker, services.external_issue_trackers.any?) end + def has_wiki? + wiki_enabled? || has_external_wiki? + end + def external_wiki if has_external_wiki.nil? cache_has_external_wiki # Populate -- cgit v1.2.1 From 9c2d061ad468e6a47d21617fb2c6b874e22c13bc Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Wed, 24 Aug 2016 11:43:44 +0100 Subject: Drop unused CI tables and files These tables, web hooks and services, are unused but where not dropped with the commits d5c91bb9a601a1a344d94763654f0b0996857497 and 2988e1fbf50b3c9e803a9358933e3e969e64dcc3. The file was left too, but never called. --- app/services/ci/web_hook_service.rb | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 app/services/ci/web_hook_service.rb (limited to 'app') diff --git a/app/services/ci/web_hook_service.rb b/app/services/ci/web_hook_service.rb deleted file mode 100644 index 92e6df442b4..00000000000 --- a/app/services/ci/web_hook_service.rb +++ /dev/null @@ -1,35 +0,0 @@ -module Ci - class WebHookService - def build_end(build) - execute_hooks(build.project, build_data(build)) - end - - def execute_hooks(project, data) - project.web_hooks.each do |web_hook| - async_execute_hook(web_hook, data) - end - end - - def async_execute_hook(hook, data) - Sidekiq::Client.enqueue(Ci::WebHookWorker, hook.id, data) - end - - def build_data(build) - project = build.project - data = {} - data.merge!({ - build_id: build.id, - build_name: build.name, - build_status: build.status, - build_started_at: build.started_at, - build_finished_at: build.finished_at, - project_id: project.id, - project_name: project.name, - gitlab_url: project.gitlab_url, - ref: build.ref, - before_sha: build.before_sha, - sha: build.sha, - }) - end - end -end -- cgit v1.2.1 From 12784559316fc2c3860641bee9c6f8e2bc12c4ba Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Wed, 3 Aug 2016 22:20:08 -0500 Subject: Change logo animation to CSS --- app/assets/javascripts/logo.js | 42 +--------- app/assets/stylesheets/framework.scss | 1 + app/assets/stylesheets/framework/header.scss | 32 +------- app/assets/stylesheets/framework/logo.scss | 118 +++++++++++++++++++++++++++ app/assets/stylesheets/framework/mixins.scss | 5 ++ app/views/shared/_logo.svg | 16 ++-- 6 files changed, 135 insertions(+), 79 deletions(-) create mode 100644 app/assets/stylesheets/framework/logo.scss (limited to 'app') diff --git a/app/assets/javascripts/logo.js b/app/assets/javascripts/logo.js index 218f24fe908..e5d4fd44c96 100644 --- a/app/assets/javascripts/logo.js +++ b/app/assets/javascripts/logo.js @@ -1,50 +1,12 @@ (function() { - var clearHighlights, currentTimer, defaultClass, delay, firstPiece, pieceIndex, pieces, start, stop, work; - Turbolinks.enableProgressBar(); - defaultClass = 'tanuki-shape'; - - pieces = ['path#tanuki-right-cheek', 'path#tanuki-right-eye, path#tanuki-right-ear', 'path#tanuki-nose', 'path#tanuki-left-eye, path#tanuki-left-ear', 'path#tanuki-left-cheek']; - - pieceIndex = 0; - - firstPiece = pieces[0]; - - currentTimer = null; - - delay = 150; - - clearHighlights = function() { - return $("." + defaultClass + ".highlight").attr('class', defaultClass); - }; - start = function() { - clearHighlights(); - pieceIndex = 0; - if (pieces[0] !== firstPiece) { - pieces.reverse(); - } - if (currentTimer) { - clearInterval(currentTimer); - } - return currentTimer = setInterval(work, delay); + $('.tanuki-logo').addClass('animate'); }; stop = function() { - clearInterval(currentTimer); - return clearHighlights(); - }; - - work = function() { - clearHighlights(); - $(pieces[pieceIndex]).attr('class', defaultClass + " highlight"); - if (pieceIndex === pieces.length - 1) { - pieceIndex = 0; - return pieces.reverse(); - } else { - return pieceIndex++; - } + $('.tanuki-logo').removeClass('animate'); }; $(document).on('page:fetch', start); diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index a306b8f3f29..d5cca1b10fb 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -24,6 +24,7 @@ @import "framework/issue_box.scss"; @import "framework/jquery.scss"; @import "framework/lists.scss"; +@import "framework/logo.scss"; @import "framework/markdown_area.scss"; @import "framework/mobile.scss"; @import "framework/modal.scss"; diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 0c607071840..afe4a276ae5 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -2,16 +2,6 @@ * Application Header * */ -@mixin tanuki-logo-colors($path-color) { - fill: $path-color; - transition: all 0.8s; - - &:hover, - &.highlight { - fill: lighten($path-color, 25%); - transition: all 0.1s; - } -} header { transition: padding $sidebar-transition-duration; @@ -25,7 +15,7 @@ header { margin: 8px 0; text-align: center; - #tanuki-logo, img { + .tanuki-logo, img { height: 36px; } } @@ -205,26 +195,6 @@ header { } } -#tanuki-logo { - - #tanuki-left-ear, - #tanuki-right-ear, - #tanuki-nose { - @include tanuki-logo-colors($tanuki-red); - } - - #tanuki-left-eye, - #tanuki-right-eye { - @include tanuki-logo-colors($tanuki-orange); - } - - #tanuki-left-cheek, - #tanuki-right-cheek { - @include tanuki-logo-colors($tanuki-yellow); - } - -} - @media (max-width: $screen-xs-max) { header .container-fluid { font-size: 18px; diff --git a/app/assets/stylesheets/framework/logo.scss b/app/assets/stylesheets/framework/logo.scss new file mode 100644 index 00000000000..3ee3fb4cee5 --- /dev/null +++ b/app/assets/stylesheets/framework/logo.scss @@ -0,0 +1,118 @@ +@mixin unique-keyframes { + $animation-name: unique-id(); + @include webkit-prefix(animation-name, $animation-name); + + @-webkit-keyframes #{$animation-name} { + @content; + } + @keyframes #{$animation-name} { + @content; + } +} + +@mixin tanuki-logo-colors($path-color) { + fill: $path-color; + transition: all 0.8s; + + &:hover { + fill: lighten($path-color, 25%); + transition: all 0.1s; + } +} + +@mixin tanuki-second-highlight-animations($tanuki-color) { + @include unique-keyframes { + 10%, 80% { + fill: #{$tanuki-color} + } + 20%, 90% { + fill: lighten($tanuki-color, 25%); + } + } +} + +@mixin tanuki-forth-highlight-animations($tanuki-color) { + @include unique-keyframes { + 30%, 60% { + fill: #{$tanuki-color}; + } + 40%, 70% { + fill: lighten($tanuki-color, 25%); + } + } +} + +.tanuki-logo { + + .tanuki-left-ear, + .tanuki-right-ear, + .tanuki-nose { + @include tanuki-logo-colors($tanuki-red); + } + + .tanuki-left-eye, + .tanuki-right-eye { + @include tanuki-logo-colors($tanuki-orange); + } + + .tanuki-left-cheek, + .tanuki-right-cheek { + @include tanuki-logo-colors($tanuki-yellow); + } + + &.animate { + .tanuki-shape { + @include webkit-prefix(animation-duration, 1.5s); + @include webkit-prefix(animation-iteration-count, infinite); + } + + .tanuki-left-cheek { + @include unique-keyframes { + 0%, 10%, 100% { + fill: lighten($tanuki-yellow, 25%); + } + 90% { + fill: $tanuki-yellow; + } + } + } + + .tanuki-left-eye { + @include tanuki-second-highlight-animations($tanuki-orange); + } + + .tanuki-left-ear { + @include tanuki-second-highlight-animations($tanuki-red); + } + + .tanuki-nose { + @include unique-keyframes { + 20%, 70% { + fill: $tanuki-red; + } + 30%, 80% { + fill: lighten($tanuki-red, 25%); + } + } + } + + .tanuki-right-eye { + @include tanuki-forth-highlight-animations($tanuki-orange); + } + + .tanuki-right-ear { + @include tanuki-forth-highlight-animations($tanuki-red); + } + + .tanuki-right-cheek { + @include unique-keyframes { + 40% { + fill: $tanuki-yellow; + } + 60% { + fill: lighten($tanuki-yellow, 25%); + } + } + } + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss index d2d60ed7196..856642400a6 100644 --- a/app/assets/stylesheets/framework/mixins.scss +++ b/app/assets/stylesheets/framework/mixins.scss @@ -129,3 +129,8 @@ color: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.1); } + +@mixin webkit-prefix($property, $value) { + #{'-webkit-' + $property}: $value; + #{$property}: $value; +} diff --git a/app/views/shared/_logo.svg b/app/views/shared/_logo.svg index b07f1c5603e..9b67422da2c 100644 --- a/app/views/shared/_logo.svg +++ b/app/views/shared/_logo.svg @@ -1,9 +1,9 @@ -
              You\'re all done!
              '); return _this.updateBadges(data); }; })(this) diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index d320d3bcc1e..6bcc37042ea 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -66,7 +66,7 @@ - if @todos.any? .js-todos-options{ data: {per_page: @todos.limit_value, current_page: @todos.current_page, total_pages: @todos.total_pages} } - @todos.group_by(&:project).each do |group| - .panel.panel-default.panel-small.js-todos-list + .panel.panel-default.panel-small - project = group[0] .panel-heading = link_to project.name_with_namespace, namespace_project_path(project.namespace, project) -- cgit v1.2.1 From 325de662ce79ea75348c303e05b2f0045835193e Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Mon, 29 Aug 2016 18:17:11 -0300 Subject: Don't create groups for unallowed users when importing projects --- app/controllers/import/base_controller.rb | 6 +++++- app/controllers/import/bitbucket_controller.rb | 13 ++++--------- app/controllers/import/github_controller.rb | 7 +------ app/controllers/import/gitlab_controller.rb | 9 ++------- app/helpers/import_helper.rb | 5 +++++ app/views/import/bitbucket/status.html.haml | 2 +- app/views/import/github/status.html.haml | 2 +- app/views/import/gitlab/status.html.haml | 2 +- 8 files changed, 20 insertions(+), 26 deletions(-) (limited to 'app') diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb index 7e8597a5eb3..1ca33bc5d22 100644 --- a/app/controllers/import/base_controller.rb +++ b/app/controllers/import/base_controller.rb @@ -1,12 +1,16 @@ class Import::BaseController < ApplicationController private - def get_or_create_namespace + def find_or_create_namespace(name, owner) begin + @target_namespace = params[:new_namespace].presence || name + @target_namespace = current_user.namespace_path if name == owner || !current_user.can_create_group? + namespace = Group.create!(name: @target_namespace, path: @target_namespace, owner: current_user) namespace.add_owner(current_user) rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid namespace = Namespace.find_by_path_or_name(@target_namespace) + unless current_user.can?(:create_projects, namespace) @already_been_taken = true return false diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 944c73d139a..94e213b8743 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -35,15 +35,10 @@ class Import::BitbucketController < Import::BaseController end def create - @repo_id = params[:repo_id] || "" - repo = client.project(@repo_id.gsub("___", "/")) - @project_name = repo["slug"] - - repo_owner = repo["owner"] - repo_owner = current_user.username if repo_owner == client.user["user"]["username"] - @target_namespace = params[:new_namespace].presence || repo_owner - - namespace = get_or_create_namespace || (render and return) + @repo_id = params[:repo_id].to_s + repo = client.project(@repo_id.gsub('___', '/')) + @project_name = repo['slug'] + namespace = find_or_create_namespace(repo['owner'], client.user['user']['username']) || (render and return) unless Gitlab::BitbucketImport::KeyAdder.new(repo, current_user, access_params).execute @access_denied = true diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb index 9c1b0eb20f4..4047e62efa2 100644 --- a/app/controllers/import/github_controller.rb +++ b/app/controllers/import/github_controller.rb @@ -41,12 +41,7 @@ class Import::GithubController < Import::BaseController @repo_id = params[:repo_id].to_i repo = client.repo(@repo_id) @project_name = repo.name - - repo_owner = repo.owner.login - repo_owner = current_user.username if repo_owner == client.user.login - @target_namespace = params[:new_namespace].presence || repo_owner - - namespace = get_or_create_namespace || (render and return) + namespace = find_or_create_namespace(repo.owner.login, client.user.login) || (render and return) @project = Gitlab::GithubImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute end diff --git a/app/controllers/import/gitlab_controller.rb b/app/controllers/import/gitlab_controller.rb index 08130ee8176..bc967e55ab1 100644 --- a/app/controllers/import/gitlab_controller.rb +++ b/app/controllers/import/gitlab_controller.rb @@ -26,13 +26,8 @@ class Import::GitlabController < Import::BaseController def create @repo_id = params[:repo_id].to_i repo = client.project(@repo_id) - @project_name = repo["name"] - - repo_owner = repo["namespace"]["path"] - repo_owner = current_user.username if repo_owner == client.user["username"] - @target_namespace = params[:new_namespace].presence || repo_owner - - namespace = get_or_create_namespace || (render and return) + @project_name = repo['name'] + namespace = find_or_create_namespace(repo['namespace']['path'], client.user['username']) || (render and return) @project = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute end diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb index 109bc1a02d1..021d2b14718 100644 --- a/app/helpers/import_helper.rb +++ b/app/helpers/import_helper.rb @@ -1,4 +1,9 @@ module ImportHelper + def import_project_target(owner, name) + namespace = current_user.can_create_group? ? owner : current_user.namespace_path + "#{namespace}/#{name}" + end + def github_project_link(path_with_namespace) link_to path_with_namespace, github_project_url(path_with_namespace), target: '_blank' end diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml index 15dd98077c8..f8b4b107513 100644 --- a/app/views/import/bitbucket/status.html.haml +++ b/app/views/import/bitbucket/status.html.haml @@ -51,7 +51,7 @@ %td = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank" %td.import-target - = "#{repo["owner"]}/#{repo["slug"]}" + = import_project_target(repo['owner'], repo['slug']) %td.import-actions.job-status = button_tag class: "btn btn-import js-add-to-import" do Import diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml index 54ff1d27c67..bd3be20c4f8 100644 --- a/app/views/import/github/status.html.haml +++ b/app/views/import/github/status.html.haml @@ -45,7 +45,7 @@ %td = github_project_link(repo.full_name) %td.import-target - = repo.full_name + = import_project_target(repo.owner.login, repo.name) %td.import-actions.job-status = button_tag class: "btn btn-import js-add-to-import" do Import diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml index fcfc6fd37f4..d31fc2e6adb 100644 --- a/app/views/import/gitlab/status.html.haml +++ b/app/views/import/gitlab/status.html.haml @@ -45,7 +45,7 @@ %td = link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank" %td.import-target - = repo["path_with_namespace"] + = import_project_target(repo['namespace']['path'], repo['name']) %td.import-actions.job-status = button_tag class: "btn btn-import js-add-to-import" do Import -- cgit v1.2.1 From ddc5b9f7236f8932c32ec9ec1d91338aab22a9e0 Mon Sep 17 00:00:00 2001 From: Bryce Date: Wed, 31 Aug 2016 18:08:52 +0200 Subject: Revert "Add last commit time to repo view" This reverts commit 8581e152ef8fa27b6670760d39b7f06dab5f796b. This creates really difficult conflicts with another MR that was worked on simulataneously. That MR mostly encompassed the aims of this commit. See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5308/commits --- app/assets/stylesheets/pages/tree.scss | 10 ---------- app/views/projects/tree/_tree_content.html.haml | 11 +++++------ 2 files changed, 5 insertions(+), 16 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 538f211c65b..9da40fe2b09 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -11,16 +11,6 @@ } } - .last-commit { - max-width: 506px; - - .last-commit-content { - @include str-truncated; - width: calc(100% - 140px); - margin-left: 3px; - } - } - .tree-table { margin-bottom: 0; diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index ca5d2d7722a..558e6146ae9 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -5,17 +5,16 @@ %tr %th Name %th Last Update - %th.hidden-xs.last-commit - Last Commit - .last-commit-content.hidden-sm + %th.hidden-xs + .pull-left Last Commit + .last-commit.hidden-sm.pull-left +   %i.fa.fa-angle-right   %small.light = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace" – - = time_ago_with_tooltip(@commit.committed_date) - – - = @commit.full_title + = truncate(@commit.title, length: 50) = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'pull-right' - if @path.present? -- cgit v1.2.1 From eba024366bdaa2d2645857fcb404ad0468b782fa Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 18 Aug 2016 11:18:25 -0500 Subject: Remove redundant js-timeago-pending from user activity log --- app/assets/javascripts/activities.js | 2 +- app/views/events/_event.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js index 5ea6086ab77..d5e11e22be5 100644 --- a/app/assets/javascripts/activities.js +++ b/app/assets/javascripts/activities.js @@ -12,7 +12,7 @@ } Activities.prototype.updateTooltips = function() { - return gl.utils.localTimeAgo($('.js-timeago', '#activity')); + return gl.utils.localTimeAgo($('.js-timeago', '.content_list')); }; Activities.prototype.reloadActivities = function() { diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml index 5c318cd3b8b..31fdcc5e21b 100644 --- a/app/views/events/_event.html.haml +++ b/app/views/events/_event.html.haml @@ -1,7 +1,7 @@ - if event.visible_to_user?(current_user) .event-item{ class: event_row_class(event) } .event-item-timestamp - #{time_ago_with_tooltip(event.created_at)} + #{time_ago_with_tooltip(event.created_at, skip_js: true)} = cache [event, current_application_settings, "v2.2"] do = author_avatar(event, size: 40) -- cgit v1.2.1 From db5244ab9054610ae13b44a0d508a339971bdcca Mon Sep 17 00:00:00 2001 From: Bryce Date: Wed, 31 Aug 2016 18:14:09 +0200 Subject: Fix repo page ui issues, show full last commit message in repo view. Integrates changes from ClemMakesApps' commit: 8581e152, although it was reverted to avoid frustrating conflicts. See MR: !5530 (diffs) --- app/assets/stylesheets/framework/variables.scss | 1 + app/assets/stylesheets/pages/tree.scss | 21 ++++++++++++++++++--- app/views/projects/refs/logs_tree.js.haml | 4 ++-- app/views/projects/tree/_blob_item.html.haml | 6 +++--- app/views/projects/tree/_tree_content.html.haml | 9 +++++---- app/views/projects/tree/_tree_item.html.haml | 6 +++--- 6 files changed, 32 insertions(+), 15 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 5da390118c6..abfae2e00fb 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -35,6 +35,7 @@ $gl-icon-color: $gl-placeholder-color; $gl-grayish-blue: #7f8fa4; $gl-gray: $gl-text-color; $gl-gray-dark: #313236; +$gl-gray-light: $gl-placeholder-color; $gl-header-color: $gl-title-color; /* diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 9da40fe2b09..e330300f9a1 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -22,6 +22,15 @@ line-height: 21px; } + .last-commit { + @include str-truncated(60%); + } + + .commit-history-link-spacer { + margin: 0 10px; + color: $table-border-color; + } + &:hover { td { background-color: $row-hover; @@ -77,11 +86,17 @@ } } - .tree_commit { - color: $gl-gray; + .tree-time-ago { + min-width: 135px; + color: $gl-gray-light; + } + + .tree-commit { + max-width: 320px; + color: $gl-gray-light; .tree-commit-link { - color: $gl-gray; + color: $gl-gray-light; &:hover { text-decoration: underline; diff --git a/app/views/projects/refs/logs_tree.js.haml b/app/views/projects/refs/logs_tree.js.haml index 8ee2aef0e61..1141168f037 100644 --- a/app/views/projects/refs/logs_tree.js.haml +++ b/app/views/projects/refs/logs_tree.js.haml @@ -5,8 +5,8 @@ :plain var row = $("table.table_#{@hex_path} tr.file_#{hexdigest(file_name)}"); - row.find("td.tree_time_ago").html('#{escape_javascript time_ago_with_tooltip(commit.committed_date)}'); - row.find("td.tree_commit").html('#{escape_javascript render("projects/tree/tree_commit_column", commit: commit)}'); + row.find("td.tree-time-ago").html('#{escape_javascript time_ago_with_tooltip(commit.committed_date)}'); + row.find("td.tree-commit").html('#{escape_javascript render("projects/tree/tree_commit_column", commit: commit)}'); - if @more_log_url :plain diff --git a/app/views/projects/tree/_blob_item.html.haml b/app/views/projects/tree/_blob_item.html.haml index a3a4dba3fa4..ee417b58cbf 100644 --- a/app/views/projects/tree/_blob_item.html.haml +++ b/app/views/projects/tree/_blob_item.html.haml @@ -4,6 +4,6 @@ - file_name = blob_item.name = link_to namespace_project_blob_path(@project.namespace, @project, tree_join(@id || @commit.id, blob_item.name)), title: file_name do %span.str-truncated= file_name - %td.tree_time_ago.cgray - = render 'projects/tree/spinner' - %td.hidden-xs.tree_commit + %td.hidden-xs.tree-commit + %td.tree-time-ago.cgray.text-right + = render 'projects/tree/spinner' \ No newline at end of file diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml index 558e6146ae9..0f7d629ab98 100644 --- a/app/views/projects/tree/_tree_content.html.haml +++ b/app/views/projects/tree/_tree_content.html.haml @@ -4,7 +4,6 @@ %thead %tr %th Name - %th Last Update %th.hidden-xs .pull-left Last Commit .last-commit.hidden-sm.pull-left @@ -14,9 +13,11 @@ %small.light = link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace" – - = truncate(@commit.title, length: 50) - = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'pull-right' - + = time_ago_with_tooltip(@commit.committed_date) + = @commit.full_title + %small.commit-history-link-spacer | + = link_to 'History', namespace_project_commits_path(@project.namespace, @project, @id), class: 'commit-history-link' + %th.text-right Last Update - if @path.present? %tr.tree-item %td.tree-item-file-name diff --git a/app/views/projects/tree/_tree_item.html.haml b/app/views/projects/tree/_tree_item.html.haml index 9577696fc0d..1ccef6d52ab 100644 --- a/app/views/projects/tree/_tree_item.html.haml +++ b/app/views/projects/tree/_tree_item.html.haml @@ -4,6 +4,6 @@ - path = flatten_tree(tree_item) = link_to namespace_project_tree_path(@project.namespace, @project, tree_join(@id || @commit.id, path)), title: path do %span.str-truncated= path - %td.tree_time_ago.cgray - = render 'projects/tree/spinner' - %td.hidden-xs.tree_commit + %td.hidden-xs.tree-commit + %td.tree-time-ago.text-right + = render 'projects/tree/spinner' \ No newline at end of file -- cgit v1.2.1 From 7b09a27e9b27c4f62cfffdc0371a01e5f191980f Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Mon, 29 Aug 2016 13:21:37 -0500 Subject: Remove prefixes from transition CSS property --- app/assets/stylesheets/framework/mixins.scss | 8 -------- app/assets/stylesheets/framework/selects.scss | 2 +- app/assets/stylesheets/pages/search.scss | 4 ++-- 3 files changed, 3 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss index 396a37bab6e..62dc2cb3fdc 100644 --- a/app/assets/stylesheets/framework/mixins.scss +++ b/app/assets/stylesheets/framework/mixins.scss @@ -9,14 +9,6 @@ border-radius: $radius; } -@mixin transition($transition) { - -webkit-transition: $transition; - -moz-transition: $transition; - -ms-transition: $transition; - -o-transition: $transition; - transition: $transition; -} - /** * Prefilled mixins * Mixins with fixed values diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index b2e22b60440..c75dacf95d9 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -151,7 +151,7 @@ background-position: right 0 bottom 6px; border: 1px solid $input-border; @include border-radius($border-radius-default); - @include transition(border-color ease-in-out .15s, box-shadow ease-in-out .15s); + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; &:focus { border-color: $input-border-focus; diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index c9d436d72ba..436fb00ba2e 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -80,7 +80,7 @@ .search-icon { @extend .fa-search; - @include transition(color .15s); + transition: color 0.15s; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; @@ -125,7 +125,7 @@ } .location-badge { - @include transition(all .15s); + transition: all 0.15s; background-color: $location-badge-active-bg; color: $white-light; } -- cgit v1.2.1 From 97b69862ad50936ad0700b23c485a38b637469a7 Mon Sep 17 00:00:00 2001 From: tiagonbotelho Date: Wed, 31 Aug 2016 12:35:23 +0100 Subject: add specs for tags finder --- app/controllers/projects/tags_controller.rb | 5 ++++- app/finders/tags_finder.rb | 29 +++++++++++++++++++++++++++++ app/views/projects/tags/index.html.haml | 5 +++-- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 app/finders/tags_finder.rb (limited to 'app') diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index 3e5de2e0d3e..6ea8ee62bc5 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -1,5 +1,6 @@ class Projects::TagsController < Projects::ApplicationController include SortingHelper + # Authorize before_action :require_non_empty_project before_action :authorize_download_code! @@ -7,7 +8,9 @@ class Projects::TagsController < Projects::ApplicationController before_action :authorize_admin_project!, only: [:destroy] def index - @sort = params[:sort] || 'name' + params[:sort] = params[:sort].presence || 'name' + + @sort = params[:sort] @tags = TagsFinder.new(@repository, params).execute @tags = Kaminari.paginate_array(@tags).page(params[:page]) diff --git a/app/finders/tags_finder.rb b/app/finders/tags_finder.rb new file mode 100644 index 00000000000..b474f0805dc --- /dev/null +++ b/app/finders/tags_finder.rb @@ -0,0 +1,29 @@ +class TagsFinder + def initialize(repository, params) + @repository = repository + @params = params + end + + def execute + tags = @repository.tags_sorted_by(sort) + filter_by_name(tags) + end + + private + + def sort + @params[:sort].presence + end + + def search + @params[:search].presence + end + + def filter_by_name(tags) + if search + tags.select { |tag| tag.name.include?(search) } + else + tags + end + end +end diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 31a023f24cf..6adbe9351dc 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -12,7 +12,8 @@ = search_field_tag :search, params[:search], { placeholder: 'Filter by tag name', id: 'tag-search', class: 'form-control search-text-input input-short', spellcheck: false } .dropdown.inline %button.dropdown-toggle.btn{ type: 'button', data: { toggle: 'dropdown'} } - %span.light= @sort.humanize + %span.light + = @sort.humanize %b.caret %ul.dropdown-menu.dropdown-menu-align-right %li @@ -22,7 +23,7 @@ = sort_title_recently_updated = link_to filter_tags_path(sort: sort_value_oldest_updated) do = sort_title_oldest_updated - - if can? current_user, :push_code, @project + - if can?(current_user, :push_code, @project) = link_to new_namespace_project_tag_path(@project.namespace, @project), class: 'btn btn-create new-tag-btn' do New tag -- cgit v1.2.1 From e293ffd48fb16c8ad15c066cfbbe1dcead7c52e0 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 30 Aug 2016 14:34:37 -0300 Subject: Refactoring Import::BaseController#find_or_create_namespace --- app/assets/javascripts/importer_status.js | 15 +++++++++------ app/controllers/import/base_controller.rb | 19 +++++++------------ app/controllers/import/bitbucket_controller.rb | 12 +++++++----- app/controllers/import/github_controller.rb | 8 ++++++-- app/controllers/import/gitlab_controller.rb | 8 ++++++-- app/views/import/base/create.js.haml | 21 +-------------------- app/views/import/base/unauthorized.js.haml | 14 ++++++++++++++ app/views/import/bitbucket/deploy_key.js.haml | 3 +++ 8 files changed, 53 insertions(+), 47 deletions(-) create mode 100644 app/views/import/base/unauthorized.js.haml create mode 100644 app/views/import/bitbucket/deploy_key.js.haml (limited to 'app') diff --git a/app/assets/javascripts/importer_status.js b/app/assets/javascripts/importer_status.js index 0f840821f53..9efad1ce943 100644 --- a/app/assets/javascripts/importer_status.js +++ b/app/assets/javascripts/importer_status.js @@ -10,21 +10,24 @@ ImporterStatus.prototype.initStatusPage = function() { $('.js-add-to-import').off('click').on('click', (function(_this) { return function(e) { - var $btn, $namespace_input, $target_field, $tr, id, new_namespace; + var $btn, $namespace_input, $target_field, $tr, id, target_namespace; $btn = $(e.currentTarget); $tr = $btn.closest('tr'); $target_field = $tr.find('.import-target'); $namespace_input = $target_field.find('input'); id = $tr.attr('id').replace('repo_', ''); - new_namespace = null; + target_namespace = null; + if ($namespace_input.length > 0) { - new_namespace = $namespace_input.prop('value'); - $target_field.empty().append(new_namespace + "/" + ($target_field.data('project_name'))); + target_namespace = $namespace_input.prop('value'); + $target_field.empty().append(target_namespace + "/" + ($target_field.data('project_name'))); } + $btn.disable().addClass('is-loading'); + return $.post(_this.import_url, { repo_id: id, - new_namespace: new_namespace + target_namespace: target_namespace }, { dataType: 'script' }); @@ -70,7 +73,7 @@ if ($('.js-importer-status').length) { var jobsImportPath = $('.js-importer-status').data('jobs-import-path'); var importPath = $('.js-importer-status').data('import-path'); - + new ImporterStatus(jobsImportPath, importPath); } }); diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb index 1ca33bc5d22..256c41e6145 100644 --- a/app/controllers/import/base_controller.rb +++ b/app/controllers/import/base_controller.rb @@ -2,21 +2,16 @@ class Import::BaseController < ApplicationController private def find_or_create_namespace(name, owner) - begin - @target_namespace = params[:new_namespace].presence || name - @target_namespace = current_user.namespace_path if name == owner || !current_user.can_create_group? + return current_user.namespace if name == owner + return current_user.namespace unless current_user.can_create_group? - namespace = Group.create!(name: @target_namespace, path: @target_namespace, owner: current_user) + begin + name = params[:target_namespace].presence || name + namespace = Group.create!(name: name, path: name, owner: current_user) namespace.add_owner(current_user) + namespace rescue ActiveRecord::RecordNotUnique, ActiveRecord::RecordInvalid - namespace = Namespace.find_by_path_or_name(@target_namespace) - - unless current_user.can?(:create_projects, namespace) - @already_been_taken = true - return false - end + Namespace.find_by_path_or_name(name) end - - namespace end end diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb index 94e213b8743..6ea54744da8 100644 --- a/app/controllers/import/bitbucket_controller.rb +++ b/app/controllers/import/bitbucket_controller.rb @@ -38,15 +38,17 @@ class Import::BitbucketController < Import::BaseController @repo_id = params[:repo_id].to_s repo = client.project(@repo_id.gsub('___', '/')) @project_name = repo['slug'] - namespace = find_or_create_namespace(repo['owner'], client.user['user']['username']) || (render and return) + @target_namespace = find_or_create_namespace(repo['owner'], client.user['user']['username']) unless Gitlab::BitbucketImport::KeyAdder.new(repo, current_user, access_params).execute - @access_denied = true - render - return + render 'deploy_key' and return end - @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute + if current_user.can?(:create_projects, @target_namespace) + @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, @target_namespace, current_user, access_params).execute + else + render 'unauthorized' + end end private diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb index 4047e62efa2..8c6bdd16383 100644 --- a/app/controllers/import/github_controller.rb +++ b/app/controllers/import/github_controller.rb @@ -41,9 +41,13 @@ class Import::GithubController < Import::BaseController @repo_id = params[:repo_id].to_i repo = client.repo(@repo_id) @project_name = repo.name - namespace = find_or_create_namespace(repo.owner.login, client.user.login) || (render and return) + @target_namespace = find_or_create_namespace(repo.owner.login, client.user.login) - @project = Gitlab::GithubImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute + if current_user.can?(:create_projects, @target_namespace) + @project = Gitlab::GithubImport::ProjectCreator.new(repo, @target_namespace, current_user, access_params).execute + else + render 'unauthorized' + end end private diff --git a/app/controllers/import/gitlab_controller.rb b/app/controllers/import/gitlab_controller.rb index bc967e55ab1..73837ffbe67 100644 --- a/app/controllers/import/gitlab_controller.rb +++ b/app/controllers/import/gitlab_controller.rb @@ -27,9 +27,13 @@ class Import::GitlabController < Import::BaseController @repo_id = params[:repo_id].to_i repo = client.project(@repo_id) @project_name = repo['name'] - namespace = find_or_create_namespace(repo['namespace']['path'], client.user['username']) || (render and return) + @target_namespace = find_or_create_namespace(repo['namespace']['path'], client.user['username']) - @project = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, current_user, access_params).execute + if current_user.can?(:create_projects, @target_namespace) + @project = Gitlab::GitlabImport::ProjectCreator.new(repo, @target_namespace, current_user, access_params).execute + else + render 'unauthorized' + end end private diff --git a/app/views/import/base/create.js.haml b/app/views/import/base/create.js.haml index 804ad88468f..8e929538351 100644 --- a/app/views/import/base/create.js.haml +++ b/app/views/import/base/create.js.haml @@ -1,23 +1,4 @@ -- if @already_been_taken - :plain - tr = $("tr#repo_#{@repo_id}") - target_field = tr.find(".import-target") - import_button = tr.find(".btn-import") - origin_target = target_field.text() - project_name = "#{@project_name}" - origin_namespace = "#{@target_namespace}" - target_field.empty() - target_field.append("

              This namespace already been taken! Please choose another one

              ") - target_field.append("") - target_field.append("/" + project_name) - target_field.data("project_name", project_name) - target_field.find('input').prop("value", origin_namespace) - import_button.enable().removeClass('is-loading') -- elsif @access_denied - :plain - job = $("tr#repo_#{@repo_id}") - job.find(".import-actions").html("

              Access denied! Please verify you can add deploy keys to this repository.

              ") -- elsif @project.persisted? +- if @project.persisted? :plain job = $("tr#repo_#{@repo_id}") job.attr("id", "project_#{@project.id}") diff --git a/app/views/import/base/unauthorized.js.haml b/app/views/import/base/unauthorized.js.haml new file mode 100644 index 00000000000..36f8069c1f7 --- /dev/null +++ b/app/views/import/base/unauthorized.js.haml @@ -0,0 +1,14 @@ +:plain + tr = $("tr#repo_#{@repo_id}") + target_field = tr.find(".import-target") + import_button = tr.find(".btn-import") + origin_target = target_field.text() + project_name = "#{@project_name}" + origin_namespace = "#{@target_namespace.path}" + target_field.empty() + target_field.append("

              This namespace has already been taken! Please choose another one.

              ") + target_field.append("") + target_field.append("/" + project_name) + target_field.data("project_name", project_name) + target_field.find('input').prop("value", origin_namespace) + import_button.enable().removeClass('is-loading') diff --git a/app/views/import/bitbucket/deploy_key.js.haml b/app/views/import/bitbucket/deploy_key.js.haml new file mode 100644 index 00000000000..81b34ab5c9d --- /dev/null +++ b/app/views/import/bitbucket/deploy_key.js.haml @@ -0,0 +1,3 @@ +:plain + job = $("tr#repo_#{@repo_id}") + job.find(".import-actions").html("

              Access denied! Please verify you can add deploy keys to this repository.

              ") -- cgit v1.2.1 From 44340fede26278a7f9d70e0fb063df9673cfc551 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Fri, 12 Aug 2016 16:05:10 -0300 Subject: Fix confidential issues should not be passed to Webhooks --- app/services/issues/base_service.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index 089b0f527e2..241efc44d36 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -14,6 +14,8 @@ module Issues end def execute_hooks(issue, action = 'open') + return if issue.confidential? + issue_data = hook_data(issue, action) issue.project.execute_hooks(issue_data, :issue_hooks) issue.project.execute_services(issue_data, :issue_hooks) -- cgit v1.2.1 From a103a5d9cc2f496854d75492fe3f759fad0a913f Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 30 Aug 2016 17:56:26 -0300 Subject: Add option to confidential issues events to trigger Webhooks --- app/controllers/projects/hooks_controller.rb | 1 + app/models/hooks/web_hook.rb | 1 + app/views/projects/hooks/_project_hook.html.haml | 2 +- app/views/shared/web_hooks/_form.html.haml | 7 +++++++ 4 files changed, 10 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb index b5624046387..0ae8ff98009 100644 --- a/app/controllers/projects/hooks_controller.rb +++ b/app/controllers/projects/hooks_controller.rb @@ -59,6 +59,7 @@ class Projects::HooksController < Projects::ApplicationController :pipeline_events, :enable_ssl_verification, :issues_events, + :confidential_issues_events, :merge_requests_events, :note_events, :push_events, diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index f365dee3141..595602e80fe 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -4,6 +4,7 @@ class WebHook < ActiveRecord::Base default_value_for :push_events, true default_value_for :issues_events, false + default_value_for :confidential_issues_events, false default_value_for :note_events, false default_value_for :merge_requests_events, false default_value_for :tag_push_events, false diff --git a/app/views/projects/hooks/_project_hook.html.haml b/app/views/projects/hooks/_project_hook.html.haml index 3fcf1692e09..ceabe2eab3d 100644 --- a/app/views/projects/hooks/_project_hook.html.haml +++ b/app/views/projects/hooks/_project_hook.html.haml @@ -3,7 +3,7 @@ .col-md-8.col-lg-7 %strong.light-header= hook.url %div - - %w(push_events tag_push_events issues_events note_events merge_requests_events build_events pipeline_events wiki_page_events).each do |trigger| + - %w(push_events tag_push_events issues_events confidential_issues_events note_events merge_requests_events build_events pipeline_events wiki_page_events).each do |trigger| - if hook.send(trigger) %span.label.label-gray.deploy-project-label= trigger.titleize .col-md-4.col-lg-5.text-right-lg.prepend-top-5 diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml index d2ec6c3ddef..5d659eb83a9 100644 --- a/app/views/shared/web_hooks/_form.html.haml +++ b/app/views/shared/web_hooks/_form.html.haml @@ -51,6 +51,13 @@ %strong Issues events %p.light This URL will be triggered when an issue is created/updated/merged + %li + = f.check_box :confidential_issues_events, class: 'pull-left' + .prepend-left-20 + = f.label :confidential_issues_events, class: 'list-label' do + %strong Confidential Issues events + %p.light + This URL will be triggered when a confidential issue is created/updated/merged %li = f.check_box :merge_requests_events, class: 'pull-left' .prepend-left-20 -- cgit v1.2.1 From dd64f8aaf867516043dbbf559595a0ed9671ab3b Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 30 Aug 2016 18:39:25 -0300 Subject: Add option to confidential issues events to trigger services --- app/controllers/concerns/service_params.rb | 2 +- app/helpers/services_helper.rb | 6 ++++-- app/models/project_services/hipchat_service.rb | 2 +- app/models/project_services/slack_service.rb | 2 +- app/models/service.rb | 3 ++- 5 files changed, 9 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb index a69877edfd4..4cb3be41064 100644 --- a/app/controllers/concerns/service_params.rb +++ b/app/controllers/concerns/service_params.rb @@ -13,7 +13,7 @@ module ServiceParams # `issue_events` and `merge_request_events` (singular!) # See app/helpers/services_helper.rb for how we # make those event names plural as special case. - :issues_events, :merge_requests_events, + :issues_events, :confidential_issues_events, :merge_requests_events, :notify_only_broken_builds, :notify_only_broken_pipelines, :add_pusher, :send_from_committer_email, :disable_diffs, :external_wiki_url, :notify, :color, diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb index 2dd0bf5d71e..3d4abf76419 100644 --- a/app/helpers/services_helper.rb +++ b/app/helpers/services_helper.rb @@ -8,7 +8,9 @@ module ServicesHelper when "note" "Event will be triggered when someone adds a comment" when "issue" - "Event will be triggered when an issue is created/updated/merged" + "Event will be triggered when an issue is created/updated/closed" + when "confidential_issue" + "Event will be triggered when a confidential issue is created/updated/closed" when "merge_request" "Event will be triggered when a merge request is created/updated/merged" when "build" @@ -19,7 +21,7 @@ module ServicesHelper end def service_event_field_name(event) - event = event.pluralize if %w[merge_request issue].include?(event) + event = event.pluralize if %w[merge_request issue confidential_issue].include?(event) "#{event}_events" end end diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index d7c986c1a91..afebd3b6a12 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -39,7 +39,7 @@ class HipchatService < Service end def supported_events - %w(push issue merge_request note tag_push build) + %w(push issue confidential_issue merge_request note tag_push build) end def execute(data) diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb index abbc780dc1a..e6c943db2bf 100644 --- a/app/models/project_services/slack_service.rb +++ b/app/models/project_services/slack_service.rb @@ -44,7 +44,7 @@ class SlackService < Service end def supported_events - %w(push issue merge_request note tag_push build wiki_page) + %w(push issue confidential_issue merge_request note tag_push build wiki_page) end def execute(data) diff --git a/app/models/service.rb b/app/models/service.rb index 09b4717a523..7333f8d381b 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -7,6 +7,7 @@ class Service < ActiveRecord::Base default_value_for :active, false default_value_for :push_events, true default_value_for :issues_events, true + default_value_for :confidential_issues_events, true default_value_for :merge_requests_events, true default_value_for :tag_push_events, true default_value_for :note_events, true @@ -100,7 +101,7 @@ class Service < ActiveRecord::Base end def supported_events - %w(push tag_push issue merge_request wiki_page) + %w(push tag_push issue confidential_issue merge_request wiki_page) end def execute(data) -- cgit v1.2.1 From 21f10af0956c69b6a5bad6b36b7d6e12e60e7867 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 30 Aug 2016 19:11:46 -0300 Subject: Scope hooks thal will run for confidential issues --- app/models/hooks/project_hook.rb | 1 + app/models/service.rb | 1 + app/services/issues/base_service.rb | 9 ++++----- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb index 836a75b0608..c631e7a7df5 100644 --- a/app/models/hooks/project_hook.rb +++ b/app/models/hooks/project_hook.rb @@ -2,6 +2,7 @@ class ProjectHook < WebHook belongs_to :project scope :issue_hooks, -> { where(issues_events: true) } + scope :confidential_issue_hooks, -> { where(confidential_issues_events: true) } scope :note_hooks, -> { where(note_events: true) } scope :merge_request_hooks, -> { where(merge_requests_events: true) } scope :build_hooks, -> { where(build_events: true) } diff --git a/app/models/service.rb b/app/models/service.rb index 7333f8d381b..198e7247838 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -34,6 +34,7 @@ class Service < ActiveRecord::Base scope :push_hooks, -> { where(push_events: true, active: true) } scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) } scope :issue_hooks, -> { where(issues_events: true, active: true) } + scope :confidential_issue_hooks, -> { where(confidential_issues_events: true, active: true) } scope :merge_request_hooks, -> { where(merge_requests_events: true, active: true) } scope :note_hooks, -> { where(note_events: true, active: true) } scope :build_hooks, -> { where(build_events: true, active: true) } diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb index 241efc44d36..9ea3ce084ba 100644 --- a/app/services/issues/base_service.rb +++ b/app/services/issues/base_service.rb @@ -14,11 +14,10 @@ module Issues end def execute_hooks(issue, action = 'open') - return if issue.confidential? - - issue_data = hook_data(issue, action) - issue.project.execute_hooks(issue_data, :issue_hooks) - issue.project.execute_services(issue_data, :issue_hooks) + issue_data = hook_data(issue, action) + hooks_scope = issue.confidential? ? :confidential_issue_hooks : :issue_hooks + issue.project.execute_hooks(issue_data, hooks_scope) + issue.project.execute_services(issue_data, hooks_scope) end end end -- cgit v1.2.1 From 1af4989c6f448eccf554b817dc55f515165a7eee Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Wed, 31 Aug 2016 12:40:02 -0500 Subject: Center build stage columns in pipeline overview --- app/assets/stylesheets/pages/pipelines.scss | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 2d6653cd867..b56c0727660 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -2,6 +2,7 @@ .stage { max-width: 90px; width: 90px; + text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -146,6 +147,7 @@ } .stage-cell { + text-align: center; svg { height: 18px; @@ -153,10 +155,6 @@ vertical-align: middle; overflow: visible; } - - .light { - width: 3px; - } } .duration, -- cgit v1.2.1 From e71df3cdd20d5c9bcf4ecc64771a1d88babfddf8 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Tue, 30 Aug 2016 00:01:00 +1000 Subject: Order award tooltips by their created_at date --- app/models/concerns/awardable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/models/concerns/awardable.rb b/app/models/concerns/awardable.rb index 800a16ab246..e6feaf7df4f 100644 --- a/app/models/concerns/awardable.rb +++ b/app/models/concerns/awardable.rb @@ -2,7 +2,7 @@ module Awardable extend ActiveSupport::Concern included do - has_many :award_emoji, -> { includes(:user) }, as: :awardable, dependent: :destroy + has_many :award_emoji, -> { includes(:user).order(:id) }, as: :awardable, dependent: :destroy if self < Participable # By default we always load award_emoji user association -- cgit v1.2.1 From a926f1f03e8516302d08195a705fbad2e953bcbb Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Wed, 31 Aug 2016 19:54:06 -0300 Subject: Fix suggested colors options for new labels in the admin area --- app/assets/javascripts/dispatcher.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index ba64d2bcf0b..38cdc7b9fba 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -199,6 +199,7 @@ break; case 'labels': switch (path[2]) { + case 'new': case 'edit': new Labels(); } -- cgit v1.2.1 From 0d8352973bfbd3d1857657fce35284fcaf241cf7 Mon Sep 17 00:00:00 2001 From: winniehell Date: Sun, 17 Jul 2016 02:03:56 +0200 Subject: Use JavaScript tooltips for mentions (!5301) --- app/models/commit.rb | 9 --------- app/models/commit_range.rb | 7 ------- 2 files changed, 16 deletions(-) (limited to 'app') diff --git a/app/models/commit.rb b/app/models/commit.rb index 817d063e4a2..e64fd1e0c1b 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -108,15 +108,6 @@ class Commit @diff_line_count end - # Returns a string describing the commit for use in a link title - # - # Example - # - # "Commit: Alex Denisov - Project git clone panel" - def link_title - "Commit: #{author_name} - #{title}" - end - # Returns the commits title. # # Usually, the commit title is the first line of the commit message. diff --git a/app/models/commit_range.rb b/app/models/commit_range.rb index 630ee9601e0..656a242c265 100644 --- a/app/models/commit_range.rb +++ b/app/models/commit_range.rb @@ -4,12 +4,10 @@ # # range = CommitRange.new('f3f85602...e86e1013', project) # range.exclude_start? # => false -# range.reference_title # => "Commits f3f85602 through e86e1013" # range.to_s # => "f3f85602...e86e1013" # # range = CommitRange.new('f3f856029bc5f966c5a7ee24cf7efefdd20e6019..e86e1013709735be5bb767e2b228930c543f25ae', project) # range.exclude_start? # => true -# range.reference_title # => "Commits f3f85602^ through e86e1013" # range.to_param # => {from: "f3f856029bc5f966c5a7ee24cf7efefdd20e6019^", to: "e86e1013709735be5bb767e2b228930c543f25ae"} # range.to_s # => "f3f85602..e86e1013" # @@ -109,11 +107,6 @@ class CommitRange reference end - # Returns a String for use in a link's title attribute - def reference_title - "Commits #{sha_start} through #{sha_to}" - end - # Return a Hash of parameters for passing to a URL helper # # See `namespace_project_compare_url` -- cgit v1.2.1 From 91c215f9a7c5f1bd33eee4d8587bc80a92863071 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Wed, 31 Aug 2016 20:58:58 -0500 Subject: make projects dropdown accessible --- app/assets/stylesheets/framework/header.scss | 4 ++++ app/helpers/projects_helper.rb | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 2b4fc0fb068..e981de241ce 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -160,11 +160,15 @@ header { } .dropdown-toggle-caret { + color: $gl-text-color; + border: transparent; + background: transparent; position: relative; top: -2px; width: 12px; line-height: 12px; margin-left: 5px; + padding: 0; font-size: 10px; text-align: center; cursor: pointer; diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index f07077bd133..7a90a0bb465 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -61,7 +61,9 @@ module ProjectsHelper project_link = link_to simple_sanitize(project.name), project_path(project), { class: "project-item-select-holder" } if current_user - project_link << icon("chevron-down", class: "dropdown-toggle-caret js-projects-dropdown-toggle", aria: { label: "Toggle switch project dropdown" }, data: { target: ".js-dropdown-menu-projects", toggle: "dropdown" }) + project_link << button_tag(type: 'button', class: "dropdown-toggle-caret js-projects-dropdown-toggle", aria: { label: "Toggle switch project dropdown" }, data: { target: ".js-dropdown-menu-projects", toggle: "dropdown" }) do + icon("chevron-down") + end end full_title = "#{namespace_link} / #{project_link}".html_safe -- cgit v1.2.1 From 523002e40f79ad85ffa6ce74b8ff405c17429cb6 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Wed, 31 Aug 2016 21:16:04 -0500 Subject: prevent project dropdown chevron from disappearing in small viewports --- app/assets/stylesheets/framework/header.scss | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index e981de241ce..d3e787937e6 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -136,6 +136,8 @@ header { } .title { + position: relative; + padding-right: 20px; margin: 0; font-size: 19px; max-width: 400px; @@ -163,11 +165,11 @@ header { color: $gl-text-color; border: transparent; background: transparent; - position: relative; - top: -2px; + position: absolute; + right: 3px; width: 12px; - line-height: 12px; - margin-left: 5px; + line-height: 19px; + margin-top: (($header-height - 19) / 2); padding: 0; font-size: 10px; text-align: center; -- cgit v1.2.1 From cf1174c673ce4244236b64f25e34f1a609552ede Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Wed, 31 Aug 2016 22:55:56 -0500 Subject: add extra viewport breakpoint for project name width --- app/assets/stylesheets/framework/header.scss | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index d3e787937e6..1036219172e 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -150,7 +150,11 @@ header { vertical-align: top; white-space: nowrap; - @media (max-width: $screen-sm-max) { + @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { + max-width: 300px; + } + + @media (max-width: $screen-xs-max) { max-width: 190px; } -- cgit v1.2.1 From d326d3428da89b943bb5f1d4d396f21b3e999ff7 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Mon, 29 Aug 2016 07:46:30 -0700 Subject: Optimize branch lookups and force a repository reload for Repository#find_branch If `git gc` runs and `Repository` has an instance to `Rugged::Repository`, a bug in libgit2 may cause the instance to return a stale value or a missing branch. This change not only optimizes the branch lookup so we don't have to iterate through every branch, but it also works around the `git gc` issue by forcing a repository reload every time `Repository#find_branch` is called. See: https://github.com/libgit2/libgit2/issues/1534 Closes #15392, #21470 --- app/models/repository.rb | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/repository.rb b/app/models/repository.rb index 91bdafdac99..f891e8374d2 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -120,8 +120,21 @@ class Repository commits end - def find_branch(name) - raw_repository.branches.find { |branch| branch.name == name } + def find_branch(name, fresh_repo: true) + # Since the Repository object may have in-memory index changes, invalidating the memoized Repository object may + # cause unintended side effects. Because finding a branch is a read-only operation, we can safely instantiate + # a new repo here to ensure a consistent state to avoid a libgit2 bug where concurrent access (e.g. via git gc) + # may cause the branch to "disappear" erroneously or have the wrong SHA. + # + # See: https://github.com/libgit2/libgit2/issues/1534 and https://gitlab.com/gitlab-org/gitlab-ce/issues/15392 + raw_repo = + if fresh_repo + Gitlab::Git::Repository.new(path_to_repo) + else + raw_repository + end + + raw_repo.find_branch(name) end def find_tag(name) -- cgit v1.2.1 From 25c84fd629e72acc753b920a35eb3cfe1cf93035 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 1 Sep 2016 10:48:34 +0100 Subject: Fixed issue where moving issue & then scrolling stop new page loading --- app/assets/javascripts/boards/models/list.js.es6 | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/boards/models/list.js.es6 b/app/assets/javascripts/boards/models/list.js.es6 index 296a033071e..91fd620fdb3 100644 --- a/app/assets/javascripts/boards/models/list.js.es6 +++ b/app/assets/javascripts/boards/models/list.js.es6 @@ -52,7 +52,7 @@ class List { } nextPage () { - if (Math.floor(this.issues.length / 20) === this.page) { + if (this.issuesSize > this.issues.length) { this.page++; return this.getIssues(false); @@ -94,15 +94,20 @@ class List { } addIssue (issue, listFrom) { - this.issues.push(issue); + if (!this.findIssue(issue.id)) { + this.issues.push(issue); - if (this.label) { - issue.addLabel(this.label); - } + if (this.label) { + issue.addLabel(this.label); + } - if (listFrom) { - this.issuesSize++; - gl.boardService.moveIssue(issue.id, listFrom.id, this.id); + if (listFrom) { + this.issuesSize++; + gl.boardService.moveIssue(issue.id, listFrom.id, this.id) + .then(() => { + listFrom.getIssues(false); + }); + } } } -- cgit v1.2.1 From 195d79dce0ea424aeea78e8ad35ece83bd708641 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 1 Sep 2016 05:38:58 -0600 Subject: path const and prevent default location --- app/assets/javascripts/user.js.es6 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/user.js.es6 b/app/assets/javascripts/user.js.es6 index c934afa458a..d644a1c0bc6 100644 --- a/app/assets/javascripts/user.js.es6 +++ b/app/assets/javascripts/user.js.es6 @@ -22,12 +22,12 @@ hideProjectLimitMessage() { $('.hide-project-limit-message').on('click', e => { - const path = '/'; + e.preventDefault(); + const path = gon.relative_url_root || '/'; $.cookie('hide_project_limit_message', 'false', { path: path }); $(this).parents('.project-limit-message').remove(); - e.preventDefault(); return; }); } -- cgit v1.2.1 From 0d45972c936bc498b2e9d1f552099b4679afd607 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 1 Sep 2016 05:40:38 -0600 Subject: single quotes for 'placement': 'top' k-v --- app/assets/javascripts/user.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/user.js.es6 b/app/assets/javascripts/user.js.es6 index d644a1c0bc6..f9cdf82f529 100644 --- a/app/assets/javascripts/user.js.es6 +++ b/app/assets/javascripts/user.js.es6 @@ -9,7 +9,7 @@ placeTop() { $('.profile-groups-avatars').tooltip({ - "placement": "top" + 'placement': 'top' }); } -- cgit v1.2.1 From ee419bf48b16b91b2a47f877f169fbf531f8ae11 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 1 Sep 2016 05:54:10 -0600 Subject: no string wraps on keys --- app/assets/javascripts/user.js.es6 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/assets/javascripts/user.js.es6 b/app/assets/javascripts/user.js.es6 index f9cdf82f529..833f35df59b 100644 --- a/app/assets/javascripts/user.js.es6 +++ b/app/assets/javascripts/user.js.es6 @@ -9,7 +9,7 @@ placeTop() { $('.profile-groups-avatars').tooltip({ - 'placement': 'top' + placement: 'top' }); } -- cgit v1.2.1 From ed51734030f94aa7e0636d8527b4bdae05c9de6b Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 21 Jun 2016 13:12:02 +0200 Subject: Handle error on trace raw download with old builds (DB stored) --- app/controllers/projects/builds_controller.rb | 2 +- app/models/ci/build.rb | 4 ++++ app/views/projects/builds/_sidebar.html.haml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 12195c3cbb8..4127337cbf2 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -78,7 +78,7 @@ class Projects::BuildsController < Projects::ApplicationController end def raw - if @build.has_trace? + if @build.has_trace_file? send_file @build.path_to_trace, type: 'text/plain; charset=utf-8', disposition: 'inline' else render_404 diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 23c8de6f650..76142c4b2b6 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -208,6 +208,10 @@ module Ci end end + def has_trace_file? + File.exist?(path_to_trace) || (project.ci_id && File.exist?(old_path_to_trace)) + end + def has_trace? raw_trace.present? end diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml index 5b0b58e087b..49c8bd11634 100644 --- a/app/views/projects/builds/_sidebar.html.haml +++ b/app/views/projects/builds/_sidebar.html.haml @@ -100,7 +100,7 @@ - elsif @build.runner \##{@build.runner.id} .btn-group.btn-group-justified{ role: :group } - - if @build.has_trace? + - if @build.has_trace_file? = link_to 'Raw', raw_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' - if @build.active? = link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post -- cgit v1.2.1 From 56011f9f697b7ca42f786735a2249014dd3ef18d Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 25 Aug 2016 13:53:20 +0200 Subject: Refactorize CI::Build model --- app/models/ci/build.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 76142c4b2b6..8a8f848d328 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -209,7 +209,7 @@ module Ci end def has_trace_file? - File.exist?(path_to_trace) || (project.ci_id && File.exist?(old_path_to_trace)) + File.exist?(path_to_trace) || has_old_trace_file? end def has_trace? @@ -219,7 +219,7 @@ module Ci def raw_trace if File.file?(path_to_trace) File.read(path_to_trace) - elsif project.ci_id && File.file?(old_path_to_trace) + elsif has_old_trace_file? # Temporary fix for build trace data integrity File.read(old_path_to_trace) else @@ -228,6 +228,14 @@ module Ci end end + ## + # Deprecated + # + # This is a hotfix for CI build data integrity, see #4246 + def has_old_trace_file? + project.ci_id && File.exist?(old_path_to_trace) + end + def trace trace = raw_trace if project && trace.present? && project.runners_token.present? -- cgit v1.2.1 From 77295de4076835d6080a9868fe7cb0c08522e141 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 25 Aug 2016 13:53:49 +0200 Subject: Change 404 to 410 error when raw trace is unavailable --- app/controllers/application_controller.rb | 4 ++++ app/controllers/projects/builds_controller.rb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index bd4ba384b29..78ed12db516 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -117,6 +117,10 @@ class ApplicationController < ActionController::Base render file: Rails.root.join("public", "404"), layout: false, status: "404" end + def render_410 + render file: Rails.root.join("public", "410"), layout: false, status: "410" + end + def no_cache_headers response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" response.headers["Pragma"] = "no-cache" diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 4127337cbf2..79d774195f8 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -81,7 +81,7 @@ class Projects::BuildsController < Projects::ApplicationController if @build.has_trace_file? send_file @build.path_to_trace, type: 'text/plain; charset=utf-8', disposition: 'inline' else - render_404 + render_410 end end -- cgit v1.2.1 From c8861da76772d781f677a76506f590edc23ba251 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Tue, 30 Aug 2016 12:47:31 +0200 Subject: Update specs - add mocks to simulate old versions --- app/controllers/application_controller.rb | 4 ---- app/controllers/projects/builds_controller.rb | 4 ++-- app/models/ci/build.rb | 10 +++++++++- 3 files changed, 11 insertions(+), 7 deletions(-) (limited to 'app') diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 78ed12db516..bd4ba384b29 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -117,10 +117,6 @@ class ApplicationController < ActionController::Base render file: Rails.root.join("public", "404"), layout: false, status: "404" end - def render_410 - render file: Rails.root.join("public", "410"), layout: false, status: "410" - end - def no_cache_headers response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" response.headers["Pragma"] = "no-cache" diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 79d774195f8..77934ff9962 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -79,9 +79,9 @@ class Projects::BuildsController < Projects::ApplicationController def raw if @build.has_trace_file? - send_file @build.path_to_trace, type: 'text/plain; charset=utf-8', disposition: 'inline' + send_file @build.trace_file_path, type: 'text/plain; charset=utf-8', disposition: 'inline' else - render_410 + render_404 end end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 8a8f848d328..f219cee4a62 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -217,7 +217,7 @@ module Ci end def raw_trace - if File.file?(path_to_trace) + if File.exist?(path_to_trace) File.read(path_to_trace) elsif has_old_trace_file? # Temporary fix for build trace data integrity @@ -274,6 +274,14 @@ module Ci end end + def trace_file_path + if has_old_trace_file? + old_path_to_trace + else + path_to_trace + end + end + def dir_to_trace File.join( Settings.gitlab_ci.builds_path, -- cgit v1.2.1 From beff8b9bd077fea4bbcb09881396b57ba07f568e Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Sat, 27 Aug 2016 23:45:01 +0100 Subject: Swapped out author dropdown and started on swapping out project dropdown --- app/assets/javascripts/gl_dropdown.js | 1 + app/helpers/issuables_helper.rb | 13 ++++++++++++ app/helpers/todos_helper.rb | 26 ++++++++++-------------- app/views/dashboard/todos/index.html.haml | 33 ++++++++++++++++++++----------- 4 files changed, 46 insertions(+), 27 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 77b2082cba0..ba59ce3c956 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -202,6 +202,7 @@ var ref, ref1, ref2, ref3, searchFields, selector, self; this.el = el1; this.options = options; + console.log(this.options); this.updateLabel = bind(this.updateLabel, this); this.hidden = bind(this.hidden, this); this.opened = bind(this.opened, this); diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index b9baeb1d6c4..dcf2ef6bb0a 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -49,6 +49,19 @@ module IssuablesHelper end end + def project_dropdown_label(project_id, default_label) + return default_label if project_id.nil? + return "Any project" if project_id == "0" + + project = Project.find_by(id: project_id) + + if project + project.name_with_namespace || project.name + else + default_label + end + end + def milestone_dropdown_label(milestone_title, default_label = "Milestone") if milestone_title == Milestone::Upcoming.name milestone_title = Milestone::Upcoming.title diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 0465327060e..a9f4c8b07b5 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -78,13 +78,11 @@ module TodosHelper end def todo_actions_options - actions = [ - OpenStruct.new(id: '', title: 'Any Action'), - OpenStruct.new(id: Todo::ASSIGNED, title: 'Assigned'), - OpenStruct.new(id: Todo::MENTIONED, title: 'Mentioned') + [ + { id: '', text: 'Any Action' }, + { id: Todo::ASSIGNED, text: 'Assigned' }, + { id: Todo::MENTIONED, text: 'Mentioned' } ] - - options_from_collection_for_select(actions, 'id', 'title', params[:action_id]) end def todo_projects_options @@ -92,22 +90,18 @@ module TodosHelper projects = projects.includes(:namespace) projects = projects.map do |project| - OpenStruct.new(id: project.id, title: project.name_with_namespace) + { id: project.id, text: project.name_with_namespace } end - projects.unshift(OpenStruct.new(id: '', title: 'Any Project')) - - options_from_collection_for_select(projects, 'id', 'title', params[:project_id]) + projects.unshift({ id: '', text: 'Any Project' }).to_json end def todo_types_options - types = [ - OpenStruct.new(title: 'Any Type', name: ''), - OpenStruct.new(title: 'Issue', name: 'Issue'), - OpenStruct.new(title: 'Merge Request', name: 'MergeRequest') + [ + { text: 'Any Type', id: '' }, + { text: 'Issue', id: 'Issue' }, + { text: 'Merge Request', id: 'MergeRequest' } ] - - options_from_collection_for_select(types, 'name', 'title', params[:type]) end private diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 6bcc37042ea..42dc1fd0118 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -28,20 +28,23 @@ .row-content-block.second-block = form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form' do .filter-item.inline - = select_tag('project_id', todo_projects_options, - class: 'select2 trigger-submit', include_blank: true, - data: {placeholder: 'Project'}) + - if params[:project_id].present? + = hidden_field_tag(:project_id, params[:project_id]) + = dropdown_tag(project_dropdown_label(params[:project_id], 'Project'), options: { toggle_class: 'js-project-search js-filter-submit', title: 'Filter by project', filter: true, filterInput: 'input#search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit', + placeholder: 'Search projects', data: { data: todo_projects_options, selected: params[:project_id], field_name: 'project_id', default_label: 'Project' } }) .filter-item.inline - = users_select_tag(:author_id, selected: params[:author_id], - placeholder: 'Author', class: 'trigger-submit', any_user: "Any Author", first_user: true, current_user: true) + - if params[:author_id].present? + = hidden_field_tag(:author_id, params[:author_id]) + = dropdown_tag(user_dropdown_label(params[:author_id], 'Author'), options: { toggle_class: 'js-user-search js-filter-submit js-author-search', title: 'Filter by author', filter: true, filterInput: 'input#search', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit', + placeholder: 'Search authors', data: { any_user: 'Any Author', first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: 'author_id', default_label: 'Author' } }) .filter-item.inline - = select_tag('type', todo_types_options, - class: 'select2 trigger-submit', include_blank: true, - data: {placeholder: 'Type'}) + -# = select_tag('type', todo_types_options, + -# class: 'select2 trigger-submit', include_blank: true, + -# data: {placeholder: 'Type'}) .filter-item.inline.actions-filter - = select_tag('action_id', todo_actions_options, - class: 'select2 trigger-submit', include_blank: true, - data: {placeholder: 'Action'}) + -# = select_tag('action_id', todo_actions_options, + -# class: 'select2 trigger-submit', include_blank: true, + -# data: {placeholder: 'Action'}) .pull-right .dropdown.inline.prepend-left-10 @@ -80,6 +83,14 @@ :javascript new UsersSelect(); + $projectDropdown = $('.js-project-search'); + $projectDropdown.glDropdown({ + filterable: true, + selectable: true, + fieldName: 'project_id', + data: $projectDropdown.data('data') + }); + $('form.filter-form').on('submit', function (event) { event.preventDefault(); Turbolinks.visit(this.action + '&' + $(this).serialize()); -- cgit v1.2.1 From 0e2dd06f259a42e360cb73a9f17de46cc0ab31fd Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Sun, 28 Aug 2016 00:09:21 +0100 Subject: Completed project filter dropdown, still need to move it from inline to ProjectSelect.js (or different) --- app/assets/javascripts/gl_dropdown.js | 1 - app/helpers/issuables_helper.rb | 2 +- app/views/dashboard/todos/index.html.haml | 8 +++++++- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index ba59ce3c956..77b2082cba0 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -202,7 +202,6 @@ var ref, ref1, ref2, ref3, searchFields, selector, self; this.el = el1; this.options = options; - console.log(this.options); this.updateLabel = bind(this.updateLabel, this); this.hidden = bind(this.hidden, this); this.opened = bind(this.opened, this); diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index dcf2ef6bb0a..5c04bba323f 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -56,7 +56,7 @@ module IssuablesHelper project = Project.find_by(id: project_id) if project - project.name_with_namespace || project.name + project.name_with_namespace else default_label end diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 42dc1fd0118..ffdb88975a5 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -88,7 +88,13 @@ filterable: true, selectable: true, fieldName: 'project_id', - data: $projectDropdown.data('data') + data: $projectDropdown.data('data'), + clicked: function() { + if ($projectDropdown.hasClass('js-filter-submit')) { + console.log('booM!'); + return $projectDropdown.closest('form').submit(); + } + } }); $('form.filter-form').on('submit', function (event) { -- cgit v1.2.1 From f157a9e5144fde90dc31add4006b9132e1489aa1 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Sun, 28 Aug 2016 00:18:48 +0100 Subject: Added type and action dropdowns, need to finalize by removing all inline and polishing off the selected dropdown states --- app/views/dashboard/todos/index.html.haml | 40 ++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index ffdb88975a5..4a8536315a5 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -38,14 +38,15 @@ = dropdown_tag(user_dropdown_label(params[:author_id], 'Author'), options: { toggle_class: 'js-user-search js-filter-submit js-author-search', title: 'Filter by author', filter: true, filterInput: 'input#search', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit', placeholder: 'Search authors', data: { any_user: 'Any Author', first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: 'author_id', default_label: 'Author' } }) .filter-item.inline - -# = select_tag('type', todo_types_options, - -# class: 'select2 trigger-submit', include_blank: true, - -# data: {placeholder: 'Type'}) + - if params[:type].present? + = hidden_field_tag(:type, params[:type]) + = dropdown_tag(params[:type] || 'Type', options: { toggle_class: 'js-type-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-type js-filter-submit', + data: { data: todo_types_options, selected: params[:type], field_name: 'type', default_label: 'Type' } }) .filter-item.inline.actions-filter - -# = select_tag('action_id', todo_actions_options, - -# class: 'select2 trigger-submit', include_blank: true, - -# data: {placeholder: 'Action'}) - + - if params[:action_id].present? + = hidden_field_tag(:action_id, params[:action_id]) + = dropdown_tag(params[:action_id] || 'Action', options: { toggle_class: 'js-action-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-action js-filter-submit', + data: { data: todo_actions_options, selected: params[:action_id], field_name: 'action_id', default_label: 'Action' } }) .pull-right .dropdown.inline.prepend-left-10 %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} @@ -91,12 +92,35 @@ data: $projectDropdown.data('data'), clicked: function() { if ($projectDropdown.hasClass('js-filter-submit')) { - console.log('booM!'); return $projectDropdown.closest('form').submit(); } } }); + $typeDropdown = $('.js-type-search'); + $typeDropdown.glDropdown({ + selectable: true, + fieldName: 'type_id', + data: $typeDropdown.data('data'), + clicked: function() { + if ($typeDropdown.hasClass('js-filter-submit')) { + return $typeDropdown.closest('form').submit(); + } + } + }); + + $actionDropdown = $('.js-action-search'); + $actionDropdown.glDropdown({ + selectable: true, + fieldName: 'action_id', + data: $actionDropdown.data('data'), + clicked: function() { + if ($actionDropdown.hasClass('js-filter-submit')) { + return $actionDropdown.closest('form').submit(); + } + } + }); + $('form.filter-form').on('submit', function (event) { event.preventDefault(); Turbolinks.visit(this.action + '&' + $(this).serialize()); -- cgit v1.2.1 From 922b38a0bea8c5b8610120dfb5ea168db713f3e3 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Sun, 28 Aug 2016 16:24:48 +0100 Subject: Removed inline JS and improved dropdown labels --- app/assets/javascripts/todos.js | 56 +++++++++++++++++++++++++++++++ app/helpers/todos_helper.rb | 16 +++++++-- app/views/dashboard/todos/index.html.haml | 53 +++-------------------------- 3 files changed, 73 insertions(+), 52 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/todos.js b/app/assets/javascripts/todos.js index 06605320a35..ef1eadfb9c0 100644 --- a/app/assets/javascripts/todos.js +++ b/app/assets/javascripts/todos.js @@ -13,6 +13,7 @@ this.perPage = this.el.data('perPage'); this.clearListeners(); this.initBtnListeners(); + this.initFilters(); } Todos.prototype.clearListeners = function() { @@ -27,6 +28,61 @@ return $('.todo').on('click', this.goToTodoUrl); }; + Todos.prototype.initFilters = function() { + new UsersSelect(); + this.initProjectFilterDropdown(); + this.initTypeFilterDropdown(); + this.initActionFilterDropdown(); + + $('form.filter-form').on('submit', function (event) { + event.preventDefault(); + Turbolinks.visit(this.action + '&' + $(this).serialize()); + }); + }; + + Todos.prototype.initProjectFilterDropdown = function() { + $projectDropdown = $('.js-project-search'); + $projectDropdown.glDropdown({ + filterable: true, + selectable: true, + fieldName: 'project_id', + data: $projectDropdown.data('data'), + clicked: function() { + if ($projectDropdown.hasClass('js-filter-submit')) { + return $projectDropdown.closest('form.filter-form').submit(); + } + } + }); + }; + + Todos.prototype.initTypeFilterDropdown = function() { + $typeDropdown = $('.js-type-search'); + $typeDropdown.glDropdown({ + selectable: true, + fieldName: 'type', + data: $typeDropdown.data('data'), + clicked: function() { + if ($typeDropdown.hasClass('js-filter-submit')) { + return $typeDropdown.closest('form.filter-form').submit(); + } + } + }); + }; + + Todos.prototype.initActionFilterDropdown = function() { + $actionDropdown = $('.js-action-search'); + $actionDropdown.glDropdown({ + selectable: true, + fieldName: 'action_id', + data: $actionDropdown.data('data'), + clicked: function() { + if ($actionDropdown.hasClass('js-filter-submit')) { + return $actionDropdown.closest('form.filter-form').submit(); + } + } + }); + }; + Todos.prototype.doneClicked = function(e) { var $this; e.preventDefault(); diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index a9f4c8b07b5..1e86f648203 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -98,12 +98,22 @@ module TodosHelper def todo_types_options [ - { text: 'Any Type', id: '' }, - { text: 'Issue', id: 'Issue' }, - { text: 'Merge Request', id: 'MergeRequest' } + { id: '', text: 'Any Type' }, + { id: 'Issue', text: 'Issue' }, + { id: 'MergeRequest', text: 'Merge Request' } ] end + def todo_actions_dropdown_label(selected_action_id, default_action) + selected_action = todo_actions_options.find { |action| action[:id] == selected_action_id.to_i} + selected_action ? selected_action[:text] : default_action + end + + def todo_types_dropdown_label(selected_type, default_type) + selected_type = todo_types_options.find { |type| type[:id] == selected_type && type[:id] != '' } + selected_type ? selected_type[:text] : default_type + end + private def show_todo_state?(todo) diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 4a8536315a5..70dd4db6aaf 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -40,13 +40,13 @@ .filter-item.inline - if params[:type].present? = hidden_field_tag(:type, params[:type]) - = dropdown_tag(params[:type] || 'Type', options: { toggle_class: 'js-type-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-type js-filter-submit', - data: { data: todo_types_options, selected: params[:type], field_name: 'type', default_label: 'Type' } }) + = dropdown_tag(todo_types_dropdown_label(params[:type], 'Type'), options: { toggle_class: 'js-type-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-type js-filter-submit', + data: { data: todo_types_options } }) .filter-item.inline.actions-filter - if params[:action_id].present? = hidden_field_tag(:action_id, params[:action_id]) - = dropdown_tag(params[:action_id] || 'Action', options: { toggle_class: 'js-action-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-action js-filter-submit', - data: { data: todo_actions_options, selected: params[:action_id], field_name: 'action_id', default_label: 'Action' } }) + = dropdown_tag(todo_actions_dropdown_label(params[:action_id], 'Action'), options: { toggle_class: 'js-action-search js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-action js-filter-submit', + data: { data: todo_actions_options }}) .pull-right .dropdown.inline.prepend-left-10 %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} @@ -80,48 +80,3 @@ = paginate @todos, theme: "gitlab" - else .nothing-here-block You're all done! - -:javascript - new UsersSelect(); - - $projectDropdown = $('.js-project-search'); - $projectDropdown.glDropdown({ - filterable: true, - selectable: true, - fieldName: 'project_id', - data: $projectDropdown.data('data'), - clicked: function() { - if ($projectDropdown.hasClass('js-filter-submit')) { - return $projectDropdown.closest('form').submit(); - } - } - }); - - $typeDropdown = $('.js-type-search'); - $typeDropdown.glDropdown({ - selectable: true, - fieldName: 'type_id', - data: $typeDropdown.data('data'), - clicked: function() { - if ($typeDropdown.hasClass('js-filter-submit')) { - return $typeDropdown.closest('form').submit(); - } - } - }); - - $actionDropdown = $('.js-action-search'); - $actionDropdown.glDropdown({ - selectable: true, - fieldName: 'action_id', - data: $actionDropdown.data('data'), - clicked: function() { - if ($actionDropdown.hasClass('js-filter-submit')) { - return $actionDropdown.closest('form').submit(); - } - } - }); - - $('form.filter-form').on('submit', function (event) { - event.preventDefault(); - Turbolinks.visit(this.action + '&' + $(this).serialize()); - }); -- cgit v1.2.1 From 0ccdb41ced96c304658cf88b0869c5b78a4f15b7 Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Tue, 30 Aug 2016 00:28:44 +0100 Subject: Review changes, simplified dropdown init --- app/assets/javascripts/todos.js | 51 ++++++------------------------- app/views/dashboard/todos/index.html.haml | 6 ++-- 2 files changed, 13 insertions(+), 44 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/todos.js b/app/assets/javascripts/todos.js index ef1eadfb9c0..a908f730954 100644 --- a/app/assets/javascripts/todos.js +++ b/app/assets/javascripts/todos.js @@ -30,9 +30,9 @@ Todos.prototype.initFilters = function() { new UsersSelect(); - this.initProjectFilterDropdown(); - this.initTypeFilterDropdown(); - this.initActionFilterDropdown(); + this.initFilterDropdown($('.js-project-search'), 'project_id', true); + this.initFilterDropdown($('.js-type-search'), 'type'); + this.initFilterDropdown($('.js-action-search'), 'action_id'); $('form.filter-form').on('submit', function (event) { event.preventDefault(); @@ -40,47 +40,16 @@ }); }; - Todos.prototype.initProjectFilterDropdown = function() { - $projectDropdown = $('.js-project-search'); - $projectDropdown.glDropdown({ - filterable: true, + Todos.prototype.initFilterDropdown = function($dropdown, fieldName, isFilterable) { + $dropdown.glDropdown({ selectable: true, - fieldName: 'project_id', - data: $projectDropdown.data('data'), + filterable: isFilterable, + fieldName: fieldName, + data: $dropdown.data('data'), clicked: function() { - if ($projectDropdown.hasClass('js-filter-submit')) { - return $projectDropdown.closest('form.filter-form').submit(); - } + return $dropdown.closest('form.filter-form').submit(); } - }); - }; - - Todos.prototype.initTypeFilterDropdown = function() { - $typeDropdown = $('.js-type-search'); - $typeDropdown.glDropdown({ - selectable: true, - fieldName: 'type', - data: $typeDropdown.data('data'), - clicked: function() { - if ($typeDropdown.hasClass('js-filter-submit')) { - return $typeDropdown.closest('form.filter-form').submit(); - } - } - }); - }; - - Todos.prototype.initActionFilterDropdown = function() { - $actionDropdown = $('.js-action-search'); - $actionDropdown.glDropdown({ - selectable: true, - fieldName: 'action_id', - data: $actionDropdown.data('data'), - clicked: function() { - if ($actionDropdown.hasClass('js-filter-submit')) { - return $actionDropdown.closest('form.filter-form').submit(); - } - } - }); + }) }; Todos.prototype.doneClicked = function(e) { diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml index 70dd4db6aaf..9d31f31c639 100644 --- a/app/views/dashboard/todos/index.html.haml +++ b/app/views/dashboard/todos/index.html.haml @@ -30,12 +30,12 @@ .filter-item.inline - if params[:project_id].present? = hidden_field_tag(:project_id, params[:project_id]) - = dropdown_tag(project_dropdown_label(params[:project_id], 'Project'), options: { toggle_class: 'js-project-search js-filter-submit', title: 'Filter by project', filter: true, filterInput: 'input#search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit', - placeholder: 'Search projects', data: { data: todo_projects_options, selected: params[:project_id], field_name: 'project_id', default_label: 'Project' } }) + = dropdown_tag(project_dropdown_label(params[:project_id], 'Project'), options: { toggle_class: 'js-project-search js-filter-submit', title: 'Filter by project', filter: true, filterInput: 'input#project-search', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit', + placeholder: 'Search projects', data: { data: todo_projects_options } }) .filter-item.inline - if params[:author_id].present? = hidden_field_tag(:author_id, params[:author_id]) - = dropdown_tag(user_dropdown_label(params[:author_id], 'Author'), options: { toggle_class: 'js-user-search js-filter-submit js-author-search', title: 'Filter by author', filter: true, filterInput: 'input#search', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit', + = dropdown_tag(user_dropdown_label(params[:author_id], 'Author'), options: { toggle_class: 'js-user-search js-filter-submit js-author-search', title: 'Filter by author', filter: true, filterInput: 'input#author-search', dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit', placeholder: 'Search authors', data: { any_user: 'Any Author', first_user: (current_user.username if current_user), current_user: true, project_id: (@project.id if @project), selected: params[:author_id], field_name: 'author_id', default_label: 'Author' } }) .filter-item.inline - if params[:type].present? -- cgit v1.2.1 From e67a483752310e32bc4577c03dd9042565b71c0a Mon Sep 17 00:00:00 2001 From: Luke Bennett Date: Wed, 31 Aug 2016 18:33:12 +0100 Subject: Fixed project filtering --- app/assets/javascripts/todos.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/todos.js b/app/assets/javascripts/todos.js index a908f730954..23eda7d44ca 100644 --- a/app/assets/javascripts/todos.js +++ b/app/assets/javascripts/todos.js @@ -30,7 +30,7 @@ Todos.prototype.initFilters = function() { new UsersSelect(); - this.initFilterDropdown($('.js-project-search'), 'project_id', true); + this.initFilterDropdown($('.js-project-search'), 'project_id', ['text']); this.initFilterDropdown($('.js-type-search'), 'type'); this.initFilterDropdown($('.js-action-search'), 'action_id'); @@ -40,11 +40,12 @@ }); }; - Todos.prototype.initFilterDropdown = function($dropdown, fieldName, isFilterable) { + Todos.prototype.initFilterDropdown = function($dropdown, fieldName, searchFields) { $dropdown.glDropdown({ selectable: true, - filterable: isFilterable, + filterable: searchFields ? true : false, fieldName: fieldName, + search: { fields: searchFields }, data: $dropdown.data('data'), clicked: function() { return $dropdown.closest('form.filter-form').submit(); -- cgit v1.2.1 From 892dea67717c0efbd6a28f7639f34535ec0a8747 Mon Sep 17 00:00:00 2001 From: Felipe Artur Date: Mon, 1 Aug 2016 19:31:21 -0300 Subject: Project tools visibility level --- app/controllers/jwt_controller.rb | 2 +- app/controllers/projects/application_controller.rb | 2 +- app/controllers/projects/discussions_controller.rb | 2 +- app/controllers/projects/issues_controller.rb | 2 +- app/controllers/projects/labels_controller.rb | 2 +- .../projects/merge_requests_controller.rb | 2 +- app/controllers/projects/milestones_controller.rb | 2 +- app/controllers/projects/snippets_controller.rb | 2 +- app/controllers/projects_controller.rb | 18 +++- app/helpers/application_helper.rb | 2 +- app/helpers/compare_helper.rb | 2 +- app/helpers/projects_helper.rb | 19 +++++ .../concerns/project_features_compatibility.rb | 37 ++++++++ app/models/project.rb | 27 +++--- app/models/project_feature.rb | 63 ++++++++++++++ app/models/user.rb | 2 +- app/policies/project_policy.rb | 12 +-- app/services/ci/register_build_service.rb | 8 +- app/services/merge_requests/get_urls_service.rb | 2 +- app/services/projects/create_service.rb | 4 +- app/services/projects/fork_service.rb | 4 +- app/views/layouts/nav/_project_settings.html.haml | 2 +- app/views/projects/edit.html.haml | 98 +++++++++++----------- app/views/projects/graphs/_head.html.haml | 2 +- 24 files changed, 230 insertions(+), 88 deletions(-) create mode 100644 app/models/concerns/project_features_compatibility.rb create mode 100644 app/models/project_feature.rb (limited to 'app') diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb index 014b9b43ff2..66ebdcc37a7 100644 --- a/app/controllers/jwt_controller.rb +++ b/app/controllers/jwt_controller.rb @@ -37,7 +37,7 @@ class JwtController < ApplicationController def authenticate_project(login, password) if login == 'gitlab-ci-token' - Project.find_by(builds_enabled: true, runners_token: password) + Project.with_builds_enabled.find_by(runners_token: password) end end diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb index 91315a07deb..b2ff36f6538 100644 --- a/app/controllers/projects/application_controller.rb +++ b/app/controllers/projects/application_controller.rb @@ -88,6 +88,6 @@ class Projects::ApplicationController < ApplicationController end def builds_enabled - return render_404 unless @project.builds_enabled? + return render_404 unless @project.feature_available?(:builds, current_user) end end diff --git a/app/controllers/projects/discussions_controller.rb b/app/controllers/projects/discussions_controller.rb index b2e8733ccb7..d174e1145a7 100644 --- a/app/controllers/projects/discussions_controller.rb +++ b/app/controllers/projects/discussions_controller.rb @@ -38,6 +38,6 @@ class Projects::DiscussionsController < Projects::ApplicationController end def module_enabled - render_404 unless @project.merge_requests_enabled + render_404 unless @project.feature_available?(:merge_requests, current_user) end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 7c03dcd2e64..72d2d361878 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -201,7 +201,7 @@ class Projects::IssuesController < Projects::ApplicationController end def module_enabled - return render_404 unless @project.issues_enabled && @project.default_issues_tracker? + return render_404 unless @project.feature_available?(:issues, current_user) && @project.default_issues_tracker? end def redirect_to_external_issue_tracker diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb index 0ca675623e5..28fa4a5b141 100644 --- a/app/controllers/projects/labels_controller.rb +++ b/app/controllers/projects/labels_controller.rb @@ -99,7 +99,7 @@ class Projects::LabelsController < Projects::ApplicationController protected def module_enabled - unless @project.issues_enabled || @project.merge_requests_enabled + unless @project.feature_available?(:issues, current_user) || @project.feature_available?(:merge_requests, current_user) return render_404 end end diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 4f5f3b6aa09..4f9ca0097a1 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -413,7 +413,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController end def module_enabled - return render_404 unless @project.merge_requests_enabled + return render_404 unless @project.feature_available?(:merge_requests, current_user) end def validates_merge_request diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb index da2892bfb3f..ff63f22cb5b 100644 --- a/app/controllers/projects/milestones_controller.rb +++ b/app/controllers/projects/milestones_controller.rb @@ -106,7 +106,7 @@ class Projects::MilestonesController < Projects::ApplicationController end def module_enabled - unless @project.issues_enabled || @project.merge_requests_enabled + unless @project.feature_available?(:issues, current_user) || @project.feature_available?(:merge_requests, current_user) return render_404 end end diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb index 6d0a7ee1031..17ceefec3b8 100644 --- a/app/controllers/projects/snippets_controller.rb +++ b/app/controllers/projects/snippets_controller.rb @@ -94,7 +94,7 @@ class Projects::SnippetsController < Projects::ApplicationController end def module_enabled - return render_404 unless @project.snippets_enabled + return render_404 unless @project.feature_available?(:snippets, current_user) end def snippet_params diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 84d6b106cd7..eaa38fa6c98 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -303,13 +303,23 @@ class ProjectsController < Projects::ApplicationController end def project_params + project_feature_attributes = + { + project_feature_attributes: + [ + :issues_access_level, :builds_access_level, + :wiki_access_level, :merge_requests_access_level, :snippets_access_level + ] + } + params.require(:project).permit( :name, :path, :description, :issues_tracker, :tag_list, :runners_token, - :issues_enabled, :merge_requests_enabled, :snippets_enabled, :container_registry_enabled, + :container_registry_enabled, :issues_tracker_id, :default_branch, - :wiki_enabled, :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, - :builds_enabled, :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, - :public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled, :lfs_enabled + :visibility_level, :import_url, :last_activity_at, :namespace_id, :avatar, + :build_allow_git_fetch, :build_timeout_in_minutes, :build_coverage_regex, + :public_builds, :only_allow_merge_if_build_succeeds, :request_access_enabled, + :lfs_enabled, project_feature_attributes ) end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f3733b01721..5f3765cad0d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -110,7 +110,7 @@ module ApplicationHelper project = event.project # Skip if project repo is empty or MR disabled - return false unless project && !project.empty_repo? && project.merge_requests_enabled + return false unless project && !project.empty_repo? && project.feature_available?(:merge_requests, current_user) # Skip if user already created appropriate MR return false if project.merge_requests.where(source_branch: event.branch_name).opened.any? diff --git a/app/helpers/compare_helper.rb b/app/helpers/compare_helper.rb index f1dc906cab4..aa54ee07bdc 100644 --- a/app/helpers/compare_helper.rb +++ b/app/helpers/compare_helper.rb @@ -3,7 +3,7 @@ module CompareHelper from.present? && to.present? && from != to && - project.merge_requests_enabled && + project.feature_available?(:merge_requests, current_user) && project.repository.branch_names.include?(from) && project.repository.branch_names.include?(to) end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index f07077bd133..79a1eba9714 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -412,4 +412,23 @@ module ProjectsHelper message.strip.gsub(project.repository_storage_path.chomp('/'), "[REPOS PATH]") end + + def project_feature_options + { + 'Disabled' => ProjectFeature::DISABLED, + 'Only team members' => ProjectFeature::PRIVATE, + 'Everyone with access' => ProjectFeature::ENABLED + } + end + + def project_feature_access_select(field) + # Don't show option "everyone with access" if project is private + options = project_feature_options + level = @project.project_feature.public_send(field) + + options.delete('Everyone with access') if @project.private? && level != ProjectFeature::ENABLED + + options = options_for_select(options, selected: @project.project_feature.public_send(field) || ProjectFeature::ENABLED) + content_tag(:select, options, name: "project[project_feature_attributes][#{field.to_s}]", id: "project_project_feature_attributes_#{field.to_s}", class: "pull-right form-control").html_safe + end end diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb new file mode 100644 index 00000000000..9216122923e --- /dev/null +++ b/app/models/concerns/project_features_compatibility.rb @@ -0,0 +1,37 @@ +# Makes api V3 compatible with old project features permissions methods +# +# After migrating issues_enabled merge_requests_enabled builds_enabled snippets_enabled and wiki_enabled +# fields to a new table "project_features", support for the old fields is still needed in the API. + +module ProjectFeaturesCompatibility + extend ActiveSupport::Concern + + def wiki_enabled=(value) + write_feature_attribute(:wiki_access_level, value) + end + + def builds_enabled=(value) + write_feature_attribute(:builds_access_level, value) + end + + def merge_requests_enabled=(value) + write_feature_attribute(:merge_requests_access_level, value) + end + + def issues_enabled=(value) + write_feature_attribute(:issues_access_level, value) + end + + def snippets_enabled=(value) + write_feature_attribute(:snippets_access_level, value) + end + + private + + def write_feature_attribute(field, value) + build_project_feature unless project_feature + + access_level = value == "true" ? ProjectFeature::ENABLED : ProjectFeature::DISABLED + project_feature.update_attribute(field, access_level) + end +end diff --git a/app/models/project.rb b/app/models/project.rb index e5027af4a0e..a6de2c48071 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -11,24 +11,23 @@ class Project < ActiveRecord::Base include AfterCommitQueue include CaseSensitivity include TokenAuthenticatable + include ProjectFeaturesCompatibility extend Gitlab::ConfigHelper UNKNOWN_IMPORT_URL = 'http://unknown.git' + delegate :feature_available?, :builds_enabled?, :wiki_enabled?, :merge_requests_enabled?, to: :project_feature, allow_nil: true + default_value_for :archived, false default_value_for :visibility_level, gitlab_config_features.visibility_level - default_value_for :issues_enabled, gitlab_config_features.issues - default_value_for :merge_requests_enabled, gitlab_config_features.merge_requests - default_value_for :builds_enabled, gitlab_config_features.builds - default_value_for :wiki_enabled, gitlab_config_features.wiki - default_value_for :snippets_enabled, gitlab_config_features.snippets default_value_for :container_registry_enabled, gitlab_config_features.container_registry default_value_for(:repository_storage) { current_application_settings.repository_storage } default_value_for(:shared_runners_enabled) { current_application_settings.shared_runners_enabled } after_create :ensure_dir_exist after_save :ensure_dir_exist, if: :namespace_id_changed? + after_initialize :setup_project_feature # set last_activity_at to the same as created_at after_create :set_last_activity_at @@ -62,10 +61,10 @@ class Project < ActiveRecord::Base belongs_to :group, -> { where(type: Group) }, foreign_key: 'namespace_id' belongs_to :namespace - has_one :board, dependent: :destroy - has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event', foreign_key: 'project_id' + has_one :board, dependent: :destroy + # Project services has_many :services has_one :campfire_service, dependent: :destroy @@ -130,6 +129,7 @@ class Project < ActiveRecord::Base has_many :notification_settings, dependent: :destroy, as: :source has_one :import_data, dependent: :destroy, class_name: "ProjectImportData" + has_one :project_feature, dependent: :destroy has_many :commit_statuses, dependent: :destroy, class_name: 'CommitStatus', foreign_key: :gl_project_id has_many :pipelines, dependent: :destroy, class_name: 'Ci::Pipeline', foreign_key: :gl_project_id @@ -142,6 +142,7 @@ class Project < ActiveRecord::Base has_many :deployments, dependent: :destroy accepts_nested_attributes_for :variables, allow_destroy: true + accepts_nested_attributes_for :project_feature delegate :name, to: :owner, allow_nil: true, prefix: true delegate :members, to: :team, prefix: true @@ -159,8 +160,6 @@ class Project < ActiveRecord::Base length: { within: 0..255 }, format: { with: Gitlab::Regex.project_path_regex, message: Gitlab::Regex.project_path_regex_message } - validates :issues_enabled, :merge_requests_enabled, - :wiki_enabled, inclusion: { in: [true, false] } validates :namespace, presence: true validates_uniqueness_of :name, scope: :namespace_id validates_uniqueness_of :path, scope: :namespace_id @@ -196,6 +195,9 @@ class Project < ActiveRecord::Base scope :for_milestones, ->(ids) { joins(:milestones).where('milestones.id' => ids).distinct } scope :with_push, -> { joins(:events).where('events.action = ?', Event::PUSHED) } + scope :with_builds_enabled, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id').where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0') } + scope :with_issues_enabled, -> { joins('LEFT JOIN project_features ON projects.id = project_features.project_id').where('project_features.issues_access_level IS NULL or project_features.issues_access_level > 0') } + scope :active, -> { joins(:issues, :notes, :merge_requests).order('issues.created_at, notes.created_at, merge_requests.created_at DESC') } scope :abandoned, -> { where('projects.last_activity_at < ?', 6.months.ago) } @@ -1121,7 +1123,7 @@ class Project < ActiveRecord::Base end def enable_ci - self.builds_enabled = true + project_feature.update_attribute(:builds_access_level, ProjectFeature::ENABLED) end def any_runners?(&block) @@ -1288,6 +1290,11 @@ class Project < ActiveRecord::Base private + # Prevents the creation of project_feature record for every project + def setup_project_feature + build_project_feature unless project_feature + end + def default_branch_protected? current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_FULL || current_application_settings.default_branch_protection == Gitlab::Access::PROTECTION_DEV_CAN_MERGE diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb new file mode 100644 index 00000000000..9c602c582bd --- /dev/null +++ b/app/models/project_feature.rb @@ -0,0 +1,63 @@ +class ProjectFeature < ActiveRecord::Base + # == Project features permissions + # + # Grants access level to project tools + # + # Tools can be enabled only for users, everyone or disabled + # Access control is made only for non private projects + # + # levels: + # + # Disabled: not enabled for anyone + # Private: enabled only for team members + # Enabled: enabled for everyone able to access the project + # + + # Permision levels + DISABLED = 0 + PRIVATE = 10 + ENABLED = 20 + + FEATURES = %i(issues merge_requests wiki snippets builds) + + belongs_to :project + + def feature_available?(feature, user) + raise ArgumentError, 'invalid project feature' unless FEATURES.include?(feature) + + get_permission(user, public_send("#{feature}_access_level")) + end + + def builds_enabled? + return true unless builds_access_level + + builds_access_level > DISABLED + end + + def wiki_enabled? + return true unless wiki_access_level + + wiki_access_level > DISABLED + end + + def merge_requests_enabled? + return true unless merge_requests_access_level + + merge_requests_access_level > DISABLED + end + + private + + def get_permission(user, level) + case level + when DISABLED + false + when PRIVATE + user && (project.team.member?(user) || user.admin?) + when ENABLED + true + else + true + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 8f5958333d7..6996740eebd 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -433,7 +433,7 @@ class User < ActiveRecord::Base # # This logic is duplicated from `Ability#project_abilities` into a SQL form. def projects_where_can_admin_issues - authorized_projects(Gitlab::Access::REPORTER).non_archived.where.not(issues_enabled: false) + authorized_projects(Gitlab::Access::REPORTER).non_archived.with_issues_enabled end def is_admin? diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 15a9f2f0dca..acf36d422d1 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -145,28 +145,28 @@ class ProjectPolicy < BasePolicy end def disabled_features! - unless project.issues_enabled + unless project.feature_available?(:issues, user) cannot!(*named_abilities(:issue)) end - unless project.merge_requests_enabled + unless project.feature_available?(:merge_requests, user) cannot!(*named_abilities(:merge_request)) end - unless project.issues_enabled || project.merge_requests_enabled + unless project.feature_available?(:issues, user) || project.feature_available?(:merge_requests, user) cannot!(*named_abilities(:label)) cannot!(*named_abilities(:milestone)) end - unless project.snippets_enabled + unless project.feature_available?(:snippets, user) cannot!(*named_abilities(:project_snippet)) end - unless project.has_wiki? + unless project.feature_available?(:wiki, user) || project.has_external_wiki? cannot!(*named_abilities(:wiki)) end - unless project.builds_enabled + unless project.feature_available?(:builds, user) cannot!(*named_abilities(:build)) cannot!(*named_abilities(:pipeline)) cannot!(*named_abilities(:environment)) diff --git a/app/services/ci/register_build_service.rb b/app/services/ci/register_build_service.rb index 9a187f5d694..6973191b203 100644 --- a/app/services/ci/register_build_service.rb +++ b/app/services/ci/register_build_service.rb @@ -8,16 +8,18 @@ module Ci builds = if current_runner.shared? builds. - # don't run projects which have not enabled shared runners - joins(:project).where(projects: { builds_enabled: true, shared_runners_enabled: true }). + # don't run projects which have not enabled shared runners and builds + joins(:project).where(projects: { shared_runners_enabled: true }). + joins('LEFT JOIN project_features ON ci_builds.gl_project_id = project_features.project_id'). # this returns builds that are ordered by number of running builds # we prefer projects that don't use shared runners at all joins("LEFT JOIN (#{running_builds_for_shared_runners.to_sql}) AS project_builds ON ci_builds.gl_project_id=project_builds.gl_project_id"). + where('project_features.builds_access_level IS NULL or project_features.builds_access_level > 0'). order('COALESCE(project_builds.running_builds, 0) ASC', 'ci_builds.id ASC') else # do run projects which are only assigned to this runner (FIFO) - builds.where(project: current_runner.projects.where(builds_enabled: true)).order('created_at ASC') + builds.where(project: current_runner.projects.with_builds_enabled).order('created_at ASC') end build = builds.find do |build| diff --git a/app/services/merge_requests/get_urls_service.rb b/app/services/merge_requests/get_urls_service.rb index 08c1f72d65a..1262ecbc29a 100644 --- a/app/services/merge_requests/get_urls_service.rb +++ b/app/services/merge_requests/get_urls_service.rb @@ -31,7 +31,7 @@ module MergeRequests def get_branches(changes) return [] if project.empty_repo? - return [] unless project.merge_requests_enabled + return [] unless project.merge_requests_enabled? changes_list = Gitlab::ChangesList.new(changes) changes_list.map do |change| diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index 55956be2844..be749ba4a1c 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -7,7 +7,6 @@ module Projects def execute forked_from_project_id = params.delete(:forked_from_project_id) import_data = params.delete(:import_data) - @project = Project.new(params) # Make sure that the user is allowed to use the specified visibility level @@ -81,8 +80,7 @@ module Projects log_info("#{@project.owner.name} created a new project \"#{@project.name_with_namespace}\"") unless @project.gitlab_project_import? - @project.create_wiki if @project.wiki_enabled? - + @project.create_wiki if @project.feature_available?(:wiki, current_user) @project.build_missing_services @project.create_labels diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb index de6dc38cc8e..a2de4dccece 100644 --- a/app/services/projects/fork_service.rb +++ b/app/services/projects/fork_service.rb @@ -8,7 +8,6 @@ module Projects name: @project.name, path: @project.path, shared_runners_enabled: @project.shared_runners_enabled, - builds_enabled: @project.builds_enabled, namespace_id: @params[:namespace].try(:id) || current_user.namespace.id } @@ -17,6 +16,9 @@ module Projects end new_project = CreateService.new(current_user, new_params).execute + builds_access_level = @project.project_feature.builds_access_level + new_project.project_feature.update_attributes(builds_access_level: builds_access_level) + new_project end diff --git a/app/views/layouts/nav/_project_settings.html.haml b/app/views/layouts/nav/_project_settings.html.haml index 52a5bdc1a1b..613b8b7d301 100644 --- a/app/views/layouts/nav/_project_settings.html.haml +++ b/app/views/layouts/nav/_project_settings.html.haml @@ -26,7 +26,7 @@ %span Protected Branches - - if @project.builds_enabled? + - if @project.feature_available?(:builds, current_user) = nav_link(controller: :runners) do = link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do %span diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 836c6d7b83f..f6d751a343e 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -44,52 +44,56 @@ %hr %fieldset.features.append-bottom-0 %h5.prepend-top-0 - Features - .form-group - .checkbox - = f.label :issues_enabled do - = f.check_box :issues_enabled - %strong Issues - %br - %span.descr Lightweight issue tracking system for this project - .form-group - .checkbox - = f.label :merge_requests_enabled do - = f.check_box :merge_requests_enabled - %strong Merge Requests - %br - %span.descr Submit changes to be merged upstream - .form-group - .checkbox - = f.label :builds_enabled do - = f.check_box :builds_enabled - %strong Builds - %br - %span.descr Test and deploy your changes before merge - .form-group - .checkbox - = f.label :wiki_enabled do - = f.check_box :wiki_enabled - %strong Wiki - %br - %span.descr Pages for project documentation - .form-group - .checkbox - = f.label :snippets_enabled do - = f.check_box :snippets_enabled - %strong Snippets - %br - %span.descr Share code pastes with others out of git repository - - if Gitlab.config.lfs.enabled && current_user.admin? - .form-group - .checkbox - = f.label :lfs_enabled do - = f.check_box :lfs_enabled, checked: @project.lfs_enabled? - %strong LFS - %br - %span.descr - Git Large File Storage - = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') + Feature Visibility + + = f.fields_for :project_feature do |feature_fields| + .form_group.prepend-top-20 + .row + .col-md-9 + = feature_fields.label :issues_access_level, "Issues", class: 'label-light' + %span.help-block Lightweight issue tracking system for this project + .col-md-3 + = project_feature_access_select(:issues_access_level) + + .row + .col-md-9 + = feature_fields.label :merge_requests_access_level, "Merge requests", class: 'label-light' + %span.help-block Submit changes to be merged upstream + .col-md-3 + = project_feature_access_select(:merge_requests_access_level) + + .row + .col-md-9 + = feature_fields.label :builds_access_level, "Builds", class: 'label-light' + %span.help-block Submit Test and deploy your changes before merge + .col-md-3 + = project_feature_access_select(:builds_access_level) + + .row + .col-md-9 + = feature_fields.label :wiki_access_level, "Wiki", class: 'label-light' + %span.help-block Pages for project documentation + .col-md-3 + = project_feature_access_select(:wiki_access_level) + + .row + .col-md-9 + = feature_fields.label :snippets_access_level, "Snippets", class: 'label-light' + %span.help-block Share code pastes with others out of Git repository + .col-md-3 + = project_feature_access_select(:snippets_access_level) + + - if Gitlab.config.lfs.enabled && current_user.admin? + .form-group + .checkbox + = f.label :lfs_enabled do + = f.check_box :lfs_enabled, checked: @project.lfs_enabled? + %strong LFS + %br + %span.descr + Git Large File Storage + = link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs') + - if Gitlab.config.registry.enabled .form-group .checkbox @@ -98,7 +102,7 @@ %strong Container Registry %br %span.descr Enable Container Registry for this repository - %hr + = render 'merge_request_settings', f: f %hr %fieldset.features.append-bottom-default diff --git a/app/views/projects/graphs/_head.html.haml b/app/views/projects/graphs/_head.html.haml index a231d684559..082e2cb4d8c 100644 --- a/app/views/projects/graphs/_head.html.haml +++ b/app/views/projects/graphs/_head.html.haml @@ -12,7 +12,7 @@ = link_to 'Commits', commits_namespace_project_graph_path = nav_link(action: :languages) do = link_to 'Languages', languages_namespace_project_graph_path - - if @project.builds_enabled? + - if @project.feature_available?(:builds, current_user) = nav_link(action: :ci) do = link_to ci_namespace_project_graph_path do Continuous Integration -- cgit v1.2.1 From 85e494890a931b6031aed2f9f2e50d30d6f37a32 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 25 Aug 2016 16:15:44 -0500 Subject: Replace play icon font with svg --- app/assets/stylesheets/framework/dropdowns.scss | 7 +++++++ app/assets/stylesheets/pages/environments.scss | 5 +++-- app/assets/stylesheets/pages/pipelines.scss | 7 +++++++ app/views/projects/ci/builds/_build.html.haml | 2 +- app/views/projects/ci/pipelines/_pipeline.html.haml | 4 ++-- app/views/projects/deployments/_actions.haml | 4 ++-- app/views/shared/icons/_icon_play.svg | 4 +++- 7 files changed, 25 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index edb2ff01f88..b0ba112476b 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -183,6 +183,13 @@ &.dropdown-menu-user-link { line-height: 16px; } + + .icon-play { + fill: $table-text-gray; + margin-right: 6px; + height: 12px; + width: 11px; + } } .dropdown-header { diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 55f9d4a0011..d01c60ee6ab 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -4,8 +4,9 @@ margin: 0; } - .fa-play { - font-size: 14px; + .icon-play { + height: 13px; + width: 12px; } .dropdown-new { diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 2d6653cd867..7aabafe11a5 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -215,6 +215,13 @@ border-color: $border-white-normal; } } + + .btn { + .icon-play { + height: 13px; + width: 12px; + } + } } } diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index 1fdf32466f2..73de8abe55b 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -89,4 +89,4 @@ = icon('repeat') - elsif build.playable? = link_to play_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Play', class: 'btn btn-build' do - = icon('play') + = custom_icon('icon_play') diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml index b119f6edf14..bb9493f5158 100644 --- a/app/views/projects/ci/pipelines/_pipeline.html.haml +++ b/app/views/projects/ci/pipelines/_pipeline.html.haml @@ -66,13 +66,13 @@ - if actions.any? .btn-group %a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'} - = icon("play") + = custom_icon('icon_play') %b.caret %ul.dropdown-menu.dropdown-menu-align-right - actions.each do |build| %li = link_to play_namespace_project_build_path(pipeline.project.namespace, pipeline.project, build), method: :post, rel: 'nofollow' do - = icon("play") + = custom_icon('icon_play') %span= build.name.humanize - if artifacts.present? .btn-group diff --git a/app/views/projects/deployments/_actions.haml b/app/views/projects/deployments/_actions.haml index f7bf3b834ef..16d134eb6b6 100644 --- a/app/views/projects/deployments/_actions.haml +++ b/app/views/projects/deployments/_actions.haml @@ -5,13 +5,13 @@ .inline .dropdown %a.dropdown-new.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'} - = icon("play") + = custom_icon('icon_play') %b.caret %ul.dropdown-menu.dropdown-menu-align-right - actions.each do |action| %li = link_to [:play, @project.namespace.becomes(Namespace), @project, action], method: :post, rel: 'nofollow' do - = icon("play") + = custom_icon('icon_play') %span= action.name.humanize - if local_assigns.fetch(:allow_rollback, false) diff --git a/app/views/shared/icons/_icon_play.svg b/app/views/shared/icons/_icon_play.svg index 80a6d41dbf6..e965afa9a56 100644 --- a/app/views/shared/icons/_icon_play.svg +++ b/app/views/shared/icons/_icon_play.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + \ No newline at end of file -- cgit v1.2.1 From 2560fc5adbc533d87e8ca56b471ed56bc84d95f9 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Wed, 24 Aug 2016 09:38:31 -0500 Subject: Remove inconsistent font weight for sidebar's labels --- app/views/shared/issuable/_sidebar.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index c1b50e65af5..b13daaf43c9 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -118,7 +118,7 @@ = icon('spinner spin', class: 'block-loading') - if can_edit_issuable = link_to 'Edit', '#', class: 'edit-link pull-right' - .value.bold.issuable-show-labels.hide-collapsed{ class: ("has-labels" if issuable.labels_array.any?) } + .value.issuable-show-labels.hide-collapsed{ class: ("has-labels" if issuable.labels_array.any?) } - if issuable.labels_array.any? - issuable.labels_array.each do |label| = link_to_label(label, type: issuable.to_ability_name) -- cgit v1.2.1 From 191ed1faebfa486ea6b1f72ce764ece730d6e64a Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Thu, 1 Sep 2016 13:34:50 -0500 Subject: Add curve to generic commit status pipeline --- .../generic_commit_statuses/_generic_commit_status_pipeline.html.haml | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml index 31d40f6ad03..576d0bec51b 100644 --- a/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml +++ b/app/views/projects/generic_commit_statuses/_generic_commit_status_pipeline.html.haml @@ -1,4 +1,5 @@ %li.build + .curve .build-content - if subject.target_url - link_to subject.target_url do -- cgit v1.2.1 From 0ee5efbd20bf99385183618dc0bcf74deaa20075 Mon Sep 17 00:00:00 2001 From: Luke Howell Date: Thu, 1 Sep 2016 14:52:43 +0000 Subject: Prepend blank line to close message on merge request - Added an extra new line to the prepend of the Close message Fixes #21710 --- app/services/merge_requests/build_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb index 290742f1506..e57791f6818 100644 --- a/app/services/merge_requests/build_service.rb +++ b/app/services/merge_requests/build_service.rb @@ -83,7 +83,7 @@ module MergeRequests closes_issue = "Closes ##{iid}" if merge_request.description.present? - merge_request.description += closes_issue.prepend("\n") + merge_request.description += closes_issue.prepend("\n\n") else merge_request.description = closes_issue end -- cgit v1.2.1 From bf1337be949baef050ad99fc5e4c60e7ac4e3aae Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Date: Thu, 1 Sep 2016 14:28:53 -0500 Subject: Change widths of content in MR pipeline tab --- app/assets/stylesheets/pages/pipelines.scss | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 2911576b66f..ee5d9de66d8 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -474,12 +474,16 @@ .pipelines.tab-pane { .content-list.pipelines { - overflow: scroll; + overflow: auto; } .stage { - max-width: 60px; - width: 60px; + max-width: 100px; + width: 100px; + } + + .pipeline-actions { + min-width: initial; } } -- cgit v1.2.1 From 52fe6098861bf36601be6555d2b39f366795ddd3 Mon Sep 17 00:00:00 2001 From: Tomasz Maczukin Date: Thu, 1 Sep 2016 22:17:05 +0200 Subject: Refactor Ci::Build#raw_trace --- app/models/ci/build.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index f219cee4a62..61052437318 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -217,11 +217,8 @@ module Ci end def raw_trace - if File.exist?(path_to_trace) - File.read(path_to_trace) - elsif has_old_trace_file? - # Temporary fix for build trace data integrity - File.read(old_path_to_trace) + if File.exist?(trace_file_path) + File.read(trace_file_path) else # backward compatibility read_attribute :trace -- cgit v1.2.1 From f43a0470bd52132c2853582c51637a736dcce5e8 Mon Sep 17 00:00:00 2001 From: Regis Date: Thu, 1 Sep 2016 14:51:53 -0600 Subject: removed null return - renamed 'placeTop' to 'placeProfileAvatarsToTop' --- app/assets/javascripts/user.js.es6 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/user.js.es6 b/app/assets/javascripts/user.js.es6 index 833f35df59b..6889d3a7491 100644 --- a/app/assets/javascripts/user.js.es6 +++ b/app/assets/javascripts/user.js.es6 @@ -2,12 +2,12 @@ global.User = class { constructor(opts) { this.opts = opts; - this.placeTop(); + this.placeProfileAvatarsToTop(); this.initTabs(); this.hideProjectLimitMessage(); } - placeTop() { + placeProfileAvatarsToTop() { $('.profile-groups-avatars').tooltip({ placement: 'top' }); @@ -28,7 +28,6 @@ path: path }); $(this).parents('.project-limit-message').remove(); - return; }); } } -- cgit v1.2.1 From 10d9fa99e55be0d377ebd45cb767bccc7fd6b485 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 23 Aug 2016 16:28:21 -0500 Subject: Align add button on repository view --- app/assets/stylesheets/pages/tree.scss | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index 538f211c65b..cdd38442550 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -11,6 +11,10 @@ } } + .add-to-tree { + vertical-align: top; + } + .last-commit { max-width: 506px; -- cgit v1.2.1 From 9a1974aa9b9f08e90aec5cb6ea98b60f7eb86187 Mon Sep 17 00:00:00 2001 From: "Z.J. van de Weg" Date: Fri, 2 Sep 2016 08:19:14 +0200 Subject: Fix GitLab import button --- app/views/projects/new.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 0a1e2bb2cc6..fda0592dd41 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -55,7 +55,7 @@ = render 'bitbucket_import_modal' %div - if gitlab_import_enabled? - = link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless bitbucket_import_configured?}" do + = link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}" do = icon('gitlab', text: 'GitLab.com') - unless gitlab_import_configured? = render 'gitlab_import_modal' -- cgit v1.2.1 From eb6a5982652e74485242dbd54f17bd051a88f56b Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Fri, 2 Sep 2016 09:08:13 +0000 Subject: Added `.term-bold` declaration. --- app/assets/stylesheets/pages/xterm.scss | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss index 8d855ce99b0..c9846103762 100644 --- a/app/assets/stylesheets/pages/xterm.scss +++ b/app/assets/stylesheets/pages/xterm.scss @@ -20,6 +20,9 @@ $l-cyan: #8abeb7; $l-white: $ci-text-color; + .term-bold { + font-weight: bold; + } .term-italic { font-style: italic; } -- cgit v1.2.1 From a93a610bac7d9ee7c0908592b6a5d91ef0d94333 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Tue, 30 Aug 2016 16:06:40 +0200 Subject: Use 'git update-ref' for safer web commits --- app/models/repository.rb | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'app') diff --git a/app/models/repository.rb b/app/models/repository.rb index f891e8374d2..b0644259af8 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -149,7 +149,7 @@ class Repository return false unless target GitHooksService.new.execute(user, path_to_repo, oldrev, target, ref) do - rugged.branches.create(branch_name, target) + update_ref!(ref, target, oldrev) end after_create_branch @@ -181,7 +181,7 @@ class Repository ref = Gitlab::Git::BRANCH_REF_PREFIX + branch_name GitHooksService.new.execute(user, path_to_repo, oldrev, newrev, ref) do - rugged.branches.delete(branch_name) + update_ref!(ref, newrev, oldrev) end after_remove_branch @@ -215,6 +215,21 @@ class Repository rugged.references.exist?(ref) end + def update_ref!(name, newrev, oldrev) + # We use 'git update-ref' because libgit2/rugged currently does not + # offer 'compare and swap' ref updates. Without compare-and-swap we can + # (and have!) accidentally reset the ref to an earlier state, clobbering + # commits. See also https://github.com/libgit2/libgit2/issues/1534. + command = %w[git update-ref --stdin -z] + output, status = Gitlab::Popen.popen(command, path_to_repo) do |stdin| + stdin.write("update #{name}\x00#{newrev}\x00#{oldrev}\x00") + end + + return if status.zero? + + raise CommitError.new("error updating ref #{name} #{oldrev}->#{newrev}\n#{output}") + end + # Makes sure a commit is kept around when Git garbage collection runs. # Git GC will delete commits from the repository that are no longer in any # branches or tags, but we want to keep some of these commits around, for @@ -1014,15 +1029,10 @@ class Repository def commit_with_hooks(current_user, branch) update_autocrlf_option - oldrev = Gitlab::Git::BLANK_SHA ref = Gitlab::Git::BRANCH_REF_PREFIX + branch target_branch = find_branch(branch) was_empty = empty? - if !was_empty && target_branch - oldrev = target_branch.target.id - end - # Make commit newrev = yield(ref) @@ -1030,24 +1040,15 @@ class Repository raise CommitError.new('Failed to create commit') end + oldrev = rugged.lookup(newrev).parent_ids.first || Gitlab::Git::BLANK_SHA + GitHooksService.new.execute(current_user, path_to_repo, oldrev, newrev, ref) do + update_ref!(ref, newrev, oldrev) + if was_empty || !target_branch - # Create branch - rugged.references.create(ref, newrev) - # If repo was empty expire cache after_create if was_empty after_create_branch - else - # Update head - current_head = find_branch(branch).target.id - - # Make sure target branch was not changed during pre-receive hook - if current_head == oldrev - rugged.references.update(ref, newrev) - else - raise CommitError.new('Commit was rejected because branch received new push') - end end end -- cgit v1.2.1 From 4da474ca928fff916a1e8ac3bb42d81df2364431 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 12:03:49 +0100 Subject: Hides merge request section in edit project when disabled --- app/assets/javascripts/project_new.js | 8 +++---- .../projects/_merge_request_settings.html.haml | 25 ++++++++++++---------- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/project_new.js b/app/assets/javascripts/project_new.js index 798f15e40a0..06034574c8a 100644 --- a/app/assets/javascripts/project_new.js +++ b/app/assets/javascripts/project_new.js @@ -15,18 +15,18 @@ } ProjectNew.prototype.toggleSettings = function() { - this._showOrHide('#project_builds_enabled', '.builds-feature'); - return this._showOrHide('#project_merge_requests_enabled', '.merge-requests-feature'); + this._showOrHide('#project_project_feature_attributes_builds_access_level', '.builds-feature'); + this._showOrHide('#project_project_feature_attributes_merge_requests_access_level', '.merge-requests-feature'); }; ProjectNew.prototype.toggleSettingsOnclick = function() { - return $('#project_builds_enabled, #project_merge_requests_enabled').on('click', this.toggleSettings); + $('#project_project_feature_attributes_builds_access_level, #project_project_feature_attributes_merge_requests_access_level').on('change', this.toggleSettings); }; ProjectNew.prototype._showOrHide = function(checkElement, container) { var $container; $container = $(container); - if ($(checkElement).prop('checked')) { + if ($(checkElement).val() !== '0') { return $container.show(); } else { return $container.hide(); diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml index 19b4249374b..14eb47089b1 100644 --- a/app/views/projects/_merge_request_settings.html.haml +++ b/app/views/projects/_merge_request_settings.html.haml @@ -1,11 +1,14 @@ -%fieldset.builds-feature - %h5.prepend-top-0 - Merge Requests - .form-group - .checkbox - = f.label :only_allow_merge_if_build_succeeds do - = f.check_box :only_allow_merge_if_build_succeeds - %strong Only allow merge requests to be merged if the build succeeds - .help-block - Builds need to be configured to enable this feature. - = link_to icon('question-circle'), help_page_path('workflow/merge_requests', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds') +.merge-requests-feature + %fieldset.builds-feature + %hr + %h5.prepend-top-0 + Merge Requests + .form-group + .checkbox + = f.label :only_allow_merge_if_build_succeeds do + = f.check_box :only_allow_merge_if_build_succeeds + %strong Only allow merge requests to be merged if the build succeeds + %br + %span.descr + Builds need to be configured to enable this feature. + = link_to icon('question-circle'), help_page_path('workflow/merge_requests', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds') -- cgit v1.2.1 From f8513d768242dffbd0fd0230e0bbeca972bcf0ec Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 2 Sep 2016 14:51:36 +0100 Subject: Refactored code to rely less on IDs that could change --- app/assets/javascripts/project_new.js | 18 +++++++++++++----- app/helpers/projects_helper.rb | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'app') diff --git a/app/assets/javascripts/project_new.js b/app/assets/javascripts/project_new.js index 06034574c8a..a787b11f2a9 100644 --- a/app/assets/javascripts/project_new.js +++ b/app/assets/javascripts/project_new.js @@ -4,6 +4,8 @@ this.ProjectNew = (function() { function ProjectNew() { this.toggleSettings = bind(this.toggleSettings, this); + this.$selects = $('.features select'); + $('.project-edit-container').on('ajax:before', (function(_this) { return function() { $('.project-edit-container').hide(); @@ -15,17 +17,23 @@ } ProjectNew.prototype.toggleSettings = function() { - this._showOrHide('#project_project_feature_attributes_builds_access_level', '.builds-feature'); - this._showOrHide('#project_project_feature_attributes_merge_requests_access_level', '.merge-requests-feature'); + var self = this; + + this.$selects.each(function () { + var $select = $(this), + className = $select.data('field').replace(/_/g, '-') + .replace('access-level', 'feature'); + self._showOrHide($select, '.' + className); + }); }; ProjectNew.prototype.toggleSettingsOnclick = function() { - $('#project_project_feature_attributes_builds_access_level, #project_project_feature_attributes_merge_requests_access_level').on('change', this.toggleSettings); + this.$selects.on('change', this.toggleSettings); }; ProjectNew.prototype._showOrHide = function(checkElement, container) { - var $container; - $container = $(container); + var $container = $(container); + if ($(checkElement).val() !== '0') { return $container.show(); } else { diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index d6efa603223..4c685b97c03 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -431,6 +431,6 @@ module ProjectsHelper options.delete('Everyone with access') if @project.private? && level != ProjectFeature::ENABLED options = options_for_select(options, selected: @project.project_feature.public_send(field) || ProjectFeature::ENABLED) - content_tag(:select, options, name: "project[project_feature_attributes][#{field.to_s}]", id: "project_project_feature_attributes_#{field.to_s}", class: "pull-right form-control").html_safe + content_tag(:select, options, name: "project[project_feature_attributes][#{field.to_s}]", id: "project_project_feature_attributes_#{field.to_s}", class: "pull-right form-control", data: { field: field }).html_safe end end -- cgit v1.2.1 From e119f994d779878e49d8e1d785725e80b2c48b27 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 2 Sep 2016 12:29:05 +0100 Subject: Fix pagination on user snippets page --- app/assets/javascripts/snippets_list.js | 7 +++++++ app/views/snippets/_snippets.html.haml | 16 ++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 app/assets/javascripts/snippets_list.js (limited to 'app') diff --git a/app/assets/javascripts/snippets_list.js b/app/assets/javascripts/snippets_list.js new file mode 100644 index 00000000000..dce3d71aeee --- /dev/null +++ b/app/assets/javascripts/snippets_list.js @@ -0,0 +1,7 @@ +(function() { + this.gl.SnippetsList = function() { + $('.snippets-list-holder .pagination').on('ajax:success', function(e, data) { + $('.snippets-list-holder').replaceWith(data.html); + }); + }; +}).call(this); diff --git a/app/views/snippets/_snippets.html.haml b/app/views/snippets/_snippets.html.haml index 80a3e731e1d..7be4a471579 100644 --- a/app/views/snippets/_snippets.html.haml +++ b/app/views/snippets/_snippets.html.haml @@ -1,7 +1,11 @@ -%ul.content-list - = render partial: 'shared/snippets/snippet', collection: @snippets - - if @snippets.empty? - %li - .nothing-here-block Nothing here. +.snippets-list-holder + %ul.content-list + = render partial: 'shared/snippets/snippet', collection: @snippets + - if @snippets.empty? + %li + .nothing-here-block Nothing here. -= paginate @snippets, theme: 'gitlab' + = paginate @snippets, theme: 'gitlab', remote: true + +:javascript + gl.SnippetsList(); -- cgit v1.2.1 From 4f192c997f7ef52da3530786b8b37221cd548f77 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 2 Sep 2016 16:29:07 +0100 Subject: Fix expiration date picker after update --- app/views/groups/group_members/update.js.haml | 2 +- app/views/projects/project_members/update.js.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/groups/group_members/update.js.haml b/app/views/groups/group_members/update.js.haml index 742f9d7a433..3be7ed8432c 100644 --- a/app/views/groups/group_members/update.js.haml +++ b/app/views/groups/group_members/update.js.haml @@ -1,3 +1,3 @@ :plain $("##{dom_id(@group_member)}").replaceWith('#{escape_javascript(render('shared/members/member', member: @group_member))}'); - new MemberExpirationDate(); + new gl.MemberExpirationDate(); diff --git a/app/views/projects/project_members/update.js.haml b/app/views/projects/project_members/update.js.haml index 833954bc039..37e55dc72a3 100644 --- a/app/views/projects/project_members/update.js.haml +++ b/app/views/projects/project_members/update.js.haml @@ -1,3 +1,3 @@ :plain $("##{dom_id(@project_member)}").replaceWith('#{escape_javascript(render('shared/members/member', member: @project_member))}'); - new MemberExpirationDate(); + new gl.MemberExpirationDate(); -- cgit v1.2.1 From ffef94f17e16a9ca9f0c1d1b970f2354d5144357 Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Fri, 2 Sep 2016 17:54:09 +0200 Subject: Make error message appropriate for end users --- app/models/repository.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/models/repository.rb b/app/models/repository.rb index b0644259af8..414b82516bc 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -221,13 +221,13 @@ class Repository # (and have!) accidentally reset the ref to an earlier state, clobbering # commits. See also https://github.com/libgit2/libgit2/issues/1534. command = %w[git update-ref --stdin -z] - output, status = Gitlab::Popen.popen(command, path_to_repo) do |stdin| + _, status = Gitlab::Popen.popen(command, path_to_repo) do |stdin| stdin.write("update #{name}\x00#{newrev}\x00#{oldrev}\x00") end return if status.zero? - raise CommitError.new("error updating ref #{name} #{oldrev}->#{newrev}\n#{output}") + raise CommitError.new("Could not update branch #{name.sub('refs/heads/', '')}. Please refresh and try again.") end # Makes sure a commit is kept around when Git garbage collection runs. -- cgit v1.2.1 From 2fd647259874399a14f1f1fac4bddb93fef714d0 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Sat, 30 Jul 2016 14:23:46 -0500 Subject: Fix markdown anchor icon interaction --- app/assets/images/icon-link.png | Bin 729 -> 0 bytes app/assets/images/icon_anchor.svg | 1 + app/assets/stylesheets/framework/typography.scss | 27 +++++++++-------------- 3 files changed, 11 insertions(+), 17 deletions(-) delete mode 100644 app/assets/images/icon-link.png create mode 100644 app/assets/images/icon_anchor.svg (limited to 'app') diff --git a/app/assets/images/icon-link.png b/app/assets/images/icon-link.png deleted file mode 100644 index 5b55e12571c..00000000000 Binary files a/app/assets/images/icon-link.png and /dev/null differ diff --git a/app/assets/images/icon_anchor.svg b/app/assets/images/icon_anchor.svg new file mode 100644 index 00000000000..7e242586bad --- /dev/null +++ b/app/assets/images/icon_anchor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index 06874a993fa..3f8433a0e7f 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -159,25 +159,18 @@ position: relative; a.anchor { - // Setting `display: none` would prevent the anchor being scrolled to, so - // instead we set the height to 0 and it gets updated on hover. - height: 0; + left: -16px; + position: absolute; + text-decoration: none; + + &:after { + content: url('icon_anchor.svg'); + visibility: hidden; + } } - &:hover > a.anchor { - $size: 14px; - position: absolute; - right: 100%; - top: 50%; - margin-top: -11px; - margin-right: 0; - padding-right: 15px; - display: inline-block; - width: $size; - height: $size; - background-image: image-url("icon-link.png"); - background-size: contain; - background-repeat: no-repeat; + &:hover > a.anchor:after { + visibility: visible; } } } -- cgit v1.2.1 From 610fafc706de465fbefe172caa443ebc12d43ce2 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Thu, 1 Sep 2016 15:03:50 -0500 Subject: Remove suggested colors hover underline --- app/assets/stylesheets/pages/labels.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index 606459f82cd..38c7cd98e41 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -7,6 +7,7 @@ display: inline-block; margin-right: 10px; margin-bottom: 10px; + text-decoration: none; } &.suggest-colors-dropdown { -- cgit v1.2.1 From b76ef40e36c70b18fc655a153c08c8814b6edf89 Mon Sep 17 00:00:00 2001 From: Airat Shigapov Date: Sun, 4 Sep 2016 16:33:14 +0300 Subject: Fix missing flash messages on service edit page --- app/controllers/projects/services_controller.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb index 6a227d85f6f..97e6e9471e0 100644 --- a/app/controllers/projects/services_controller.rb +++ b/app/controllers/projects/services_controller.rb @@ -20,9 +20,8 @@ class Projects::ServicesController < Projects::ApplicationController def update if @service.update_attributes(service_params[:service]) redirect_to( - edit_namespace_project_service_path(@project.namespace, @project, - @service.to_param, notice: - 'Successfully updated.') + edit_namespace_project_service_path(@project.namespace, @project, @service.to_param), + notice: 'Successfully updated.' ) else render 'edit' -- cgit v1.2.1 From 4d77056af1ca5532ae8482b362b5ef466a640ae2 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 5 Sep 2016 14:15:57 +0200 Subject: Move "Only allow merge requests to be merged if the build succeeds" to new location --- app/views/projects/_merge_request_settings.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml index 14eb47089b1..80053dd501b 100644 --- a/app/views/projects/_merge_request_settings.html.haml +++ b/app/views/projects/_merge_request_settings.html.haml @@ -11,4 +11,4 @@ %br %span.descr Builds need to be configured to enable this feature. - = link_to icon('question-circle'), help_page_path('workflow/merge_requests', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds') + = link_to icon('question-circle'), help_page_path('user/project/merge_requests/merge_when_build_succeeds', anchor: 'only-allow-merge-requests-to-be-merged-if-the-build-succeeds') -- cgit v1.2.1 From bf00e0f4b2fd8994df8f7b567839f12715a05fde Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Mon, 5 Sep 2016 18:25:05 +0200 Subject: Add links to new docs in merge_requests.md and workflow/README.md --- app/views/projects/merge_requests/show/_how_to_merge.html.haml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/views/projects/merge_requests/show/_how_to_merge.html.haml b/app/views/projects/merge_requests/show/_how_to_merge.html.haml index b727efaa6a6..571e4dd1b1a 100644 --- a/app/views/projects/merge_requests/show/_how_to_merge.html.haml +++ b/app/views/projects/merge_requests/show/_how_to_merge.html.haml @@ -47,8 +47,9 @@ Note that pushing to GitLab requires write access to this repository. %p %strong Tip: - You can also checkout merge requests locally by - %a{href: 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/workflow/merge_requests.md#checkout-merge-requests-locally', target: '_blank'} following these guidelines + = succeed '.' do + You can also checkout merge requests locally by + = link_to 'following these guidelines', help_page_path('user/project/merge_requests.md', anchor: "checkout-merge-requests-locally"), target: '_blank' :javascript $(function(){ -- cgit v1.2.1 From 7f0400398d7a09fd6eb35e8058c93ab693c0c527 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Mon, 5 Sep 2016 17:38:20 +0100 Subject: Convert SnippetsList to ES6 --- app/assets/javascripts/snippets_list.js | 7 ------- app/assets/javascripts/snippets_list.js.es6 | 11 +++++++++++ 2 files changed, 11 insertions(+), 7 deletions(-) delete mode 100644 app/assets/javascripts/snippets_list.js create mode 100644 app/assets/javascripts/snippets_list.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/snippets_list.js b/app/assets/javascripts/snippets_list.js deleted file mode 100644 index dce3d71aeee..00000000000 --- a/app/assets/javascripts/snippets_list.js +++ /dev/null @@ -1,7 +0,0 @@ -(function() { - this.gl.SnippetsList = function() { - $('.snippets-list-holder .pagination').on('ajax:success', function(e, data) { - $('.snippets-list-holder').replaceWith(data.html); - }); - }; -}).call(this); diff --git a/app/assets/javascripts/snippets_list.js.es6 b/app/assets/javascripts/snippets_list.js.es6 new file mode 100644 index 00000000000..6f0996c0d2a --- /dev/null +++ b/app/assets/javascripts/snippets_list.js.es6 @@ -0,0 +1,11 @@ +(global => { + global.gl = global.gl || {}; + + gl.SnippetsList = function() { + var $holder = $('.snippets-list-holder'); + + $holder.find('.pagination').on('ajax:success', (e, data) => { + $holder.replaceWith(data.html); + }); + } +})(window); -- cgit v1.2.1 From b24555b8f41228a22d43d6876bb307bd83b9209e Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 6 Sep 2016 08:26:48 +0200 Subject: Use stage instead of type --- app/views/projects/triggers/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/triggers/index.html.haml b/app/views/projects/triggers/index.html.haml index 7f3de47d7df..867754bdf5e 100644 --- a/app/views/projects/triggers/index.html.haml +++ b/app/views/projects/triggers/index.html.haml @@ -48,7 +48,7 @@ %pre :plain trigger: - type: deploy + stage: deploy script: - "curl -X POST -F token=TOKEN -F ref=REF_NAME #{builds_trigger_url(@project.id)}" %h5.prepend-top-default -- cgit v1.2.1 From 20cbdf8065b4564855521cb5deda924a2458b962 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 6 Sep 2016 10:36:04 +0200 Subject: Clean up and refactor the triggers views --- app/views/projects/triggers/index.html.haml | 130 ++++++++++++++++------------ 1 file changed, 77 insertions(+), 53 deletions(-) (limited to 'app') diff --git a/app/views/projects/triggers/index.html.haml b/app/views/projects/triggers/index.html.haml index 867754bdf5e..f6e0b0a7c8a 100644 --- a/app/views/projects/triggers/index.html.haml +++ b/app/views/projects/triggers/index.html.haml @@ -4,65 +4,89 @@ .col-lg-3 %h4.prepend-top-0 = page_title - %p - Triggers can force a specific branch or tag to rebuild with an API call. + %p.prepend-top-20 + Triggers can force a specific branch or tag to get rebuilt with an API call. + %p.append-bottom-0 + = succeed '.' do + Learn more in the + = link_to 'triggers documentation', help_page_path('ci/triggers/README'), target: '_blank' .col-lg-9 - %h5.prepend-top-0 - Your triggers - - if @triggers.any? - .table-responsive - %table.table - %thead - %th Token - %th Last used - %th - = render partial: 'trigger', collection: @triggers, as: :trigger - - else - %p.settings-message.text-center.append-bottom-default - No triggers have been created yet. Add one using the button below. + .panel.panel-default + .panel-heading + %h4.panel-title + Manage your project's triggers + .panel-body + - if @triggers.any? + .table-responsive + %table.table + %thead + %th + %strong Token + %th + %strong Last used + %th + = render partial: 'trigger', collection: @triggers, as: :trigger + - else + %p.settings-message.text-center.append-bottom-default + No triggers have been created yet. Add one using the button below. - = form_for @trigger, url: url_for(controller: 'projects/triggers', action: 'create') do |f| - = f.submit "Add Trigger", class: 'btn btn-success' + = form_for @trigger, url: url_for(controller: 'projects/triggers', action: 'create') do |f| + = f.submit "Add trigger", class: 'btn btn-success' - %h5.prepend-top-default - Use CURL + .panel-footer - %p.light - Copy the token above, set your branch or tag name, and that reference will be rebuilt. + %p + In the following examples, you can see the exact API call you need to + make in order to rebuild a specific + %code ref + (branch or tag) with a trigger token. + %p + All you need to do is replace the + %code TOKEN + and + %code REF_NAME + with the trigger token and the branch or tag name respectively. - %pre - :plain - curl -X POST \ - -F token=TOKEN \ - -F ref=REF_NAME \ - #{builds_trigger_url(@project.id)} - %h5.prepend-top-default - Use .gitlab-ci.yml + %h5.prepend-top-default + Use cURL - %p.light - In the - %code .gitlab-ci.yml - of the dependent project, include the following snippet. - The project will rebuild at the end of the build. + %p.light + Copy one of the tokens above, set your branch or tag name, and that + reference will be rebuilt. - %pre - :plain - trigger: - stage: deploy - script: - - "curl -X POST -F token=TOKEN -F ref=REF_NAME #{builds_trigger_url(@project.id)}" - %h5.prepend-top-default - Pass build variables + %pre + :plain + curl -X POST \ + -F token=TOKEN \ + -F ref=REF_NAME \ + #{builds_trigger_url(@project.id)} + %h5.prepend-top-default + Use .gitlab-ci.yml - %p.light - Add - %code variables[VARIABLE]=VALUE - to an API request. Variable values can be used to distinguish between triggered builds and normal builds. + %p.light + In the + %code .gitlab-ci.yml + of another project, include the following snippet. + The project will be rebuilt at the end of the build. - %pre.append-bottom-0 - :plain - curl -X POST \ - -F token=TOKEN \ - -F "ref=REF_NAME" \ - -F "variables[RUN_NIGHTLY_BUILD]=true" \ - #{builds_trigger_url(@project.id)} + %pre + :plain + trigger_build: + stage: deploy + script: + - "curl -X POST -F token=TOKEN -F ref=REF_NAME #{builds_trigger_url(@project.id)}" + %h5.prepend-top-default + Pass build variables + + %p.light + Add + %code variables[VARIABLE]=VALUE + to an API request. Variable values can be used to distinguish between triggered builds and normal builds. + + %pre.append-bottom-0 + :plain + curl -X POST \ + -F token=TOKEN \ + -F "ref=REF_NAME" \ + -F "variables[RUN_NIGHTLY_BUILD]=true" \ + #{builds_trigger_url(@project.id)} -- cgit v1.2.1 From 0893911d62520822bbf1578783e76351b7cfaa37 Mon Sep 17 00:00:00 2001 From: ubudzisz Date: Thu, 4 Aug 2016 08:59:35 +0200 Subject: add js file show variables on-click show variables on-click show variables on-click remove = and add new js classes into sidebar.scss show variables by clicking button show variables by clicking button show variables by clicking button show variables by clicking button use id for a class add nicescroll add nicescroll --- app/assets/javascripts/build_variables.js | 7 +++++++ app/assets/stylesheets/framework/sidebar.scss | 13 +++++++++++++ app/views/projects/builds/_sidebar.html.haml | 6 +++--- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 app/assets/javascripts/build_variables.js (limited to 'app') diff --git a/app/assets/javascripts/build_variables.js b/app/assets/javascripts/build_variables.js new file mode 100644 index 00000000000..3b77c1d4f37 --- /dev/null +++ b/app/assets/javascripts/build_variables.js @@ -0,0 +1,7 @@ +$(function(){ + $('.reveal-variables').off('click').on('click',function(){ + $('.js-build-variable').toggle(); + $('.js-build-value').toggle().niceScroll(); + $('.reveal-variables').show(); + }); +}); diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 015fe3debf9..6eae609555b 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -226,3 +226,16 @@ header.header-pinned-nav { .right-sidebar { border-left: 1px solid $border-color; } + +.js-build-variable { + color: #c7254e; + font-size: 100%; + border-radius: 5px; +} + +.js-build-value { + padding: 2px 4px; + font-size: 100%; + color: #000; + background-color: #fff; +} diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml index 5ce36a475a9..585cc310be3 100644 --- a/app/views/projects/builds/_sidebar.html.haml +++ b/app/views/projects/builds/_sidebar.html.haml @@ -90,12 +90,12 @@ - if @build.trigger_request.variables %p - %span.build-light-text Variables: + .btn.group.btn-group-justified.reveal-variables Reveal Variables - @build.trigger_request.variables.each do |key, value| - %code - #{key}=#{value} + .hide.js-build-variable #{key} + .hide.js-build-value #{value} .block .title -- cgit v1.2.1 From 691644dc5be544af0b0793353ab7f151136f1198 Mon Sep 17 00:00:00 2001 From: ubudzisz Date: Tue, 30 Aug 2016 17:37:49 +0200 Subject: add feature test add feature test add feature test add feature test remove test to builds_spec remove feature test to builds_spec remove feature test to builds_spec add changes to methods and remove FactoryGirl add changes to methods and remove FactoryGirl adding changes to test and js file changes grammar update changelog rename file name update files after review update files after review update files after review --- app/assets/javascripts/build_variables.js | 7 ------- app/assets/javascripts/build_variables.js.es6 | 6 ++++++ app/assets/stylesheets/framework/sidebar.scss | 8 +++----- app/views/projects/builds/_sidebar.html.haml | 5 +++-- 4 files changed, 12 insertions(+), 14 deletions(-) delete mode 100644 app/assets/javascripts/build_variables.js create mode 100644 app/assets/javascripts/build_variables.js.es6 (limited to 'app') diff --git a/app/assets/javascripts/build_variables.js b/app/assets/javascripts/build_variables.js deleted file mode 100644 index 3b77c1d4f37..00000000000 --- a/app/assets/javascripts/build_variables.js +++ /dev/null @@ -1,7 +0,0 @@ -$(function(){ - $('.reveal-variables').off('click').on('click',function(){ - $('.js-build-variable').toggle(); - $('.js-build-value').toggle().niceScroll(); - $('.reveal-variables').show(); - }); -}); diff --git a/app/assets/javascripts/build_variables.js.es6 b/app/assets/javascripts/build_variables.js.es6 new file mode 100644 index 00000000000..8d3e29794a1 --- /dev/null +++ b/app/assets/javascripts/build_variables.js.es6 @@ -0,0 +1,6 @@ +$(function(){ + $('.reveal-variables').off('click').on('click',function(){ + $('.js-build').toggle().niceScroll(); + $(this).hide(); + }); +}); diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 6eae609555b..c5367c5a097 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -228,14 +228,12 @@ header.header-pinned-nav { } .js-build-variable { - color: #c7254e; - font-size: 100%; - border-radius: 5px; + color: $code-color; } .js-build-value { padding: 2px 4px; font-size: 100%; - color: #000; - background-color: #fff; + color: $black; + background-color: $white-light; } diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml index 585cc310be3..ba5354a1690 100644 --- a/app/views/projects/builds/_sidebar.html.haml +++ b/app/views/projects/builds/_sidebar.html.haml @@ -94,8 +94,9 @@ - @build.trigger_request.variables.each do |key, value| - .hide.js-build-variable #{key} - .hide.js-build-value #{value} + .hide.js-build + .js-build-variable= key + .js-build-value= value .block .title -- cgit v1.2.1 From 790d7cce968260b28e451483606c44ec340f6d80 Mon Sep 17 00:00:00 2001 From: ubudzisz Date: Tue, 6 Sep 2016 11:49:40 +0200 Subject: improve code after review --- app/views/projects/builds/_sidebar.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml index ba5354a1690..56306b05934 100644 --- a/app/views/projects/builds/_sidebar.html.haml +++ b/app/views/projects/builds/_sidebar.html.haml @@ -90,7 +90,7 @@ - if @build.trigger_request.variables %p - .btn.group.btn-group-justified.reveal-variables Reveal Variables + %button.btn.group.btn-group-justified.reveal-variables Reveal Variables - @build.trigger_request.variables.each do |key, value| -- cgit v1.2.1 From 651f4c8e9bae6d8e94dac02e51ef5c258c62aed0 Mon Sep 17 00:00:00 2001 From: ubudzisz Date: Tue, 6 Sep 2016 13:03:48 +0200 Subject: remove css selectors --- app/assets/stylesheets/framework/sidebar.scss | 11 ----------- app/assets/stylesheets/pages/builds.scss | 10 ++++++++++ 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index c5367c5a097..015fe3debf9 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -226,14 +226,3 @@ header.header-pinned-nav { .right-sidebar { border-left: 1px solid $border-color; } - -.js-build-variable { - color: $code-color; -} - -.js-build-value { - padding: 2px 4px; - font-size: 100%; - color: $black; - background-color: $white-light; -} diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 23255f34710..614405aa5c1 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -115,6 +115,16 @@ width: 100%; } + .js-build-variable { + color: $code-color; + } + + .js-build-value { + padding: 2px 4px; + color: $black; + background-color: $white-light; + } + .build-sidebar-header { padding: 0 $gl-padding $gl-padding; -- cgit v1.2.1