summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml4
-rw-r--r--app/assets/javascripts/boards/components/board_card.js.es63
-rw-r--r--app/assets/javascripts/boards/components/board_list.js.es66
-rw-r--r--app/assets/javascripts/environments/components/environment_item.js.es68
-rw-r--r--app/assets/javascripts/extensions/element.js.es62
-rw-r--r--app/assets/javascripts/lib/utils/custom_event_polyfill.js.es612
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js8
-rw-r--r--app/assets/stylesheets/pages/notes.scss8
-rw-r--r--app/views/projects/boards/components/_board_list.html.haml2
-rw-r--r--app/views/projects/boards/components/_card.html.haml1
-rw-r--r--app/views/projects/edit.html.haml13
-rw-r--r--changelogs/unreleased/api-delete-group-share.yml4
-rw-r--r--changelogs/unreleased/issue-boards-dragging-fix.yml4
-rw-r--r--doc/api/projects.md19
-rw-r--r--doc/workflow/lfs/manage_large_binaries_with_git_lfs.md10
-rw-r--r--lib/api/projects.rb13
-rw-r--r--lib/api/sidekiq_metrics.rb36
-rw-r--r--lib/gitlab/identifier.rb6
-rw-r--r--spec/javascripts/build_spec.js.es61
-rw-r--r--spec/javascripts/merge_request_widget_spec.js2
-rw-r--r--spec/lib/gitlab/identifier_spec.rb5
-rw-r--r--spec/requests/api/projects_spec.rb30
-rw-r--r--spec/views/projects/edit.html.haml_spec.rb24
-rw-r--r--vendor/assets/javascripts/timeago.js (renamed from app/assets/javascripts/lib/utils/timeago.js)8
24 files changed, 158 insertions, 71 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f7528849c09..3c357c489f8 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -20,7 +20,7 @@ before_script:
- source ./scripts/prepare_build.sh
- cp config/gitlab.yml.example config/gitlab.yml
- bundle --version
- - '[ "$USE_BUNDLE_INSTALL" != "true" ] || retry bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}"'
+ - '[ "$USE_BUNDLE_INSTALL" != "true" ] || retry bundle install --without postgres production --jobs $(nproc) $FLAGS'
- retry gem install knapsack
- '[ "$SETUP_DB" != "true" ] || bundle exec rake db:drop db:create db:schema:load db:migrate add_limits_mysql'
@@ -328,7 +328,7 @@ migration paths:
- git checkout -f FETCH_HEAD
- cp config/resque.yml.example config/resque.yml
- sed -i 's/localhost/redis/g' config/resque.yml
- - bundle install --without postgres production --jobs $(nproc) ${FLAGS[@]} --retry=3
+ - bundle install --without postgres production --jobs $(nproc) $FLAGS --retry=3
- rake db:drop db:create db:schema:load db:seed_fu
- git checkout $CI_BUILD_REF
- source scripts/prepare_build.sh
diff --git a/app/assets/javascripts/boards/components/board_card.js.es6 b/app/assets/javascripts/boards/components/board_card.js.es6
index b1afbe7d97e..2299dafd217 100644
--- a/app/assets/javascripts/boards/components/board_card.js.es6
+++ b/app/assets/javascripts/boards/components/board_card.js.es6
@@ -54,6 +54,9 @@
mouseDown () {
this.showDetail = true;
},
+ mouseMove() {
+ this.showDetail = false;
+ },
showIssue (e) {
const targetTagName = e.target.tagName.toLowerCase();
diff --git a/app/assets/javascripts/boards/components/board_list.js.es6 b/app/assets/javascripts/boards/components/board_list.js.es6
index 379f4f0d72b..8e91cbfac75 100644
--- a/app/assets/javascripts/boards/components/board_list.js.es6
+++ b/app/assets/javascripts/boards/components/board_list.js.es6
@@ -94,12 +94,10 @@
gl.issueBoards.onStart();
},
onAdd: (e) => {
- // Add the element back to original list to allow Vue to handle DOM updates
- e.from.appendChild(e.item);
+ gl.issueBoards.BoardsStore.moveIssueToList(Store.moving.list, this.list, Store.moving.issue);
this.$nextTick(() => {
- // Update the issues once we know the element has been moved
- gl.issueBoards.BoardsStore.moveIssueToList(Store.moving.list, this.list, Store.moving.issue);
+ e.item.remove();
});
},
});
diff --git a/app/assets/javascripts/environments/components/environment_item.js.es6 b/app/assets/javascripts/environments/components/environment_item.js.es6
index 36a0fec3cab..07f49cce3dc 100644
--- a/app/assets/javascripts/environments/components/environment_item.js.es6
+++ b/app/assets/javascripts/environments/components/environment_item.js.es6
@@ -1,4 +1,7 @@
-/*= require lib/utils/timeago */
+/* global Vue */
+/* global timeago */
+
+/*= require timeago */
/*= require lib/utils/text_utility */
/*= require vue_common_component/commit */
/*= require ./environment_actions */
@@ -6,9 +9,6 @@
/*= require ./environment_stop */
/*= require ./environment_rollback */
-/* global Vue */
-/* global timeago */
-
(() => {
/**
* Envrionment Item Component
diff --git a/app/assets/javascripts/extensions/element.js.es6 b/app/assets/javascripts/extensions/element.js.es6
index afb2f0d6956..6d9b0c4bc3e 100644
--- a/app/assets/javascripts/extensions/element.js.es6
+++ b/app/assets/javascripts/extensions/element.js.es6
@@ -3,7 +3,7 @@
Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatchesSelector;
-Element.prototype.closest = function closest(selector, selectedElement = this) {
+Element.prototype.closest = Element.prototype.closest || function closest(selector, selectedElement = this) {
if (!selectedElement) return;
return selectedElement.matches(selector) ? selectedElement : Element.prototype.closest(selector, selectedElement.parentElement);
};
diff --git a/app/assets/javascripts/lib/utils/custom_event_polyfill.js.es6 b/app/assets/javascripts/lib/utils/custom_event_polyfill.js.es6
new file mode 100644
index 00000000000..5ae978010c9
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/custom_event_polyfill.js.es6
@@ -0,0 +1,12 @@
+/**
+ * CustomEvent support for IE
+ */
+if (typeof window.CustomEvent !== 'function') {
+ window.CustomEvent = function CustomEvent(e, params) {
+ const options = params || { bubbles: false, cancelable: false, detail: undefined };
+ const evt = document.createEvent('CustomEvent');
+ evt.initCustomEvent(e, options.bubbles, options.cancelable, options.detail);
+ return evt;
+ };
+ window.CustomEvent.prototype = window.Event.prototype;
+}
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index d480fdc882b..963d2851e5f 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -1,4 +1,10 @@
-/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, no-undef, comma-dangle, no-unused-expressions, prefer-template, padded-blocks, max-len */
+/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, comma-dangle, no-unused-expressions, prefer-template, padded-blocks, max-len */
+/* global timeago */
+/* global dateFormat */
+
+/*= require timeago */
+/*= require date.format */
+
(function() {
(function(w) {
var base;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 54c7caed8ed..e66c1f8d072 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -75,6 +75,8 @@ ul.notes {
display: none;
padding: 10px 0 0;
cursor: pointer;
+ position: relative;
+ z-index: 2;
&:hover {
color: $gl-link-color;
@@ -118,11 +120,11 @@ ul.notes {
&::after {
content: '';
width: 100%;
- height: 20px;
+ height: 67px;
position: absolute;
left: 0;
- bottom: 50px;
- background: linear-gradient(rgba($gray-light, .3) 0, $white-light);
+ bottom: 0;
+ background: linear-gradient(rgba($gray-light, 0.1) -100px, $white-light 100%);
}
&.hide-shade {
diff --git a/app/views/projects/boards/components/_board_list.html.haml b/app/views/projects/boards/components/_board_list.html.haml
index d86e0ed8540..34fdb1f6a74 100644
--- a/app/views/projects/boards/components/_board_list.html.haml
+++ b/app/views/projects/boards/components/_board_list.html.haml
@@ -35,7 +35,7 @@
":issue" => "issue",
":issue-link-base" => "issueLinkBase",
":disabled" => "disabled",
- "key" => "id" }
+ ":key" => "issue.id" }
%li.board-list-count.text-center{ "v-if" => "showCount" }
= icon("spinner spin", "v-show" => "list.loadingMore" )
%span{ "v-if" => "list.issues.length === list.issuesSize" }
diff --git a/app/views/projects/boards/components/_card.html.haml b/app/views/projects/boards/components/_card.html.haml
index 72b31b8cdae..34effac17b2 100644
--- a/app/views/projects/boards/components/_card.html.haml
+++ b/app/views/projects/boards/components/_card.html.haml
@@ -1,6 +1,7 @@
%li.card{ ":class" => '{ "user-can-drag": !disabled && issue.id, "is-disabled": disabled || !issue.id, "is-active": issueDetailVisible }',
":index" => "index",
"@mousedown" => "mouseDown",
+ "@mousemove" => "mouseMove",
"@mouseup" => "showIssue($event)" }
%h4.card-title
= icon("eye-slash", class: "confidential-icon", "v-if" => "issue.confidential")
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 0aa8801c2d8..3a5af2723c6 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -92,14 +92,15 @@
= project_feature_access_select(:wiki_access_level)
- if Gitlab.config.lfs.enabled && current_user.admin?
- .checkbox
- = f.label :lfs_enabled do
- = f.check_box :lfs_enabled
- %strong LFS
- %br
- %span.descr
+ .row
+ .col-md-9
+ = f.label :lfs_enabled, 'LFS', class: 'label-light'
+ %span.help-block
Git Large File Storage
= link_to icon('question-circle'), help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
+ .col-md-3
+ = f.select :lfs_enabled, [%w(Enabled true), %w(Disabled false)], {}, selected: @project.lfs_enabled?, class: 'pull-right form-control', data: { field: 'lfs_enabled' }
+
- if Gitlab.config.registry.enabled
.form-group.js-container-registry{ style: ("display: none;" if @project.project_feature.send(:repository_access_level) == 0) }
diff --git a/changelogs/unreleased/api-delete-group-share.yml b/changelogs/unreleased/api-delete-group-share.yml
new file mode 100644
index 00000000000..26cfb35bba3
--- /dev/null
+++ b/changelogs/unreleased/api-delete-group-share.yml
@@ -0,0 +1,4 @@
+---
+title: 'API: Add ability to unshare a project from a group'
+merge_request: 7662
+author: Robert Schilling
diff --git a/changelogs/unreleased/issue-boards-dragging-fix.yml b/changelogs/unreleased/issue-boards-dragging-fix.yml
new file mode 100644
index 00000000000..565e09b930b
--- /dev/null
+++ b/changelogs/unreleased/issue-boards-dragging-fix.yml
@@ -0,0 +1,4 @@
+---
+title: Fixed issue boards dragging card removing random issues
+merge_request:
+author:
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 467a880ac13..de5d3b07c21 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -1074,6 +1074,25 @@ Parameters:
| `group_access` | integer | yes | The permissions level to grant the group |
| `expires_at` | string | no | Share expiration date in ISO 8601 format: 2016-09-26 |
+### Delete a shared project link within a group
+
+Unshare the project from the group. Returns `204` and no content on success.
+
+```
+DELETE /projects/:id/share/:group_id
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID of the project or NAMESPACE/PROJECT_NAME |
+| `group_id` | integer | yes | The ID of the group |
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/projects/5/share/17
+```
+
## Hooks
Also called Project Hooks and Webhooks.
diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
index 28e6a21a229..6a7098e79d0 100644
--- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
+++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
@@ -24,6 +24,7 @@ Documentation for GitLab instance administrators is under [LFS administration do
## Requirements
* Git LFS is supported in GitLab starting with version 8.2
+* Git LFS must be enabled under project settings
* [Git LFS client](https://git-lfs.github.com) version 1.0.1 and up
## Known limitations
@@ -31,10 +32,10 @@ Documentation for GitLab instance administrators is under [LFS administration do
* Git LFS v1 original API is not supported since it was deprecated early in LFS
development
* When SSH is set as a remote, Git LFS objects still go through HTTPS
-* Any Git LFS request will ask for HTTPS credentials to be provided so good Git
+* Any Git LFS request will ask for HTTPS credentials to be provided so a good Git
credentials store is recommended
* Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have
- to add the URL to Git config manually (see #troubleshooting)
+ to add the URL to Git config manually (see [troubleshooting](#troubleshooting))
>**Note**: With 8.12 GitLab added LFS support to SSH. The Git LFS communication
still goes over HTTP, but now the SSH client passes the correct credentials
@@ -95,7 +96,7 @@ available to the project anymore. Probably the object was removed from the serve
* Local git repository is using deprecated LFS API
-### Invalid status for <url> : 501
+### Invalid status for `<url>` : 501
Git LFS will log the failures into a log file.
To view this log file, while in project directory:
@@ -106,6 +107,9 @@ git lfs logs last
If the status `error 501` is shown, it is because:
+* Git LFS is not enabled in project settings. Check your project settings and
+ enable Git LFS.
+
* Git LFS support is not enabled on the GitLab server. Check with your GitLab
administrator why Git LFS is not enabled on the server. See
[LFS administration documentation](lfs_administration.md) for instructions
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 6b856128c2e..ddfde178d30 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -438,6 +438,19 @@ module API
end
end
+ params do
+ requires :group_id, type: Integer, desc: 'The ID of the group'
+ end
+ delete ":id/share/:group_id" do
+ authorize! :admin_project, user_project
+
+ link = user_project.project_group_links.find_by(group_id: params[:group_id])
+ not_found!('Group Link') unless link
+
+ link.destroy
+ no_content!
+ end
+
# Upload a file
#
# Parameters:
diff --git a/lib/api/sidekiq_metrics.rb b/lib/api/sidekiq_metrics.rb
index d3d6827dc54..11f2b40269a 100644
--- a/lib/api/sidekiq_metrics.rb
+++ b/lib/api/sidekiq_metrics.rb
@@ -39,50 +39,22 @@ module API
end
end
- # Get Sidekiq Queue metrics
- #
- # Parameters:
- # None
- #
- # Example:
- # GET /sidekiq/queue_metrics
- #
+ desc 'Get the Sidekiq queue metrics'
get 'sidekiq/queue_metrics' do
{ queues: queue_metrics }
end
- # Get Sidekiq Process metrics
- #
- # Parameters:
- # None
- #
- # Example:
- # GET /sidekiq/process_metrics
- #
+ desc 'Get the Sidekiq process metrics'
get 'sidekiq/process_metrics' do
{ processes: process_metrics }
end
- # Get Sidekiq Job statistics
- #
- # Parameters:
- # None
- #
- # Example:
- # GET /sidekiq/job_stats
- #
+ desc 'Get the Sidekiq job statistics'
get 'sidekiq/job_stats' do
{ jobs: job_stats }
end
- # Get Sidekiq Compound metrics. Includes all previous metrics
- #
- # Parameters:
- # None
- #
- # Example:
- # GET /sidekiq/compound_metrics
- #
+ desc 'Get the Sidekiq Compound metrics. Includes queue, process, and job statistics'
get 'sidekiq/compound_metrics' do
{ queues: queue_metrics, processes: process_metrics, jobs: job_stats }
end
diff --git a/lib/gitlab/identifier.rb b/lib/gitlab/identifier.rb
index c5acf18beb5..94678b6ec40 100644
--- a/lib/gitlab/identifier.rb
+++ b/lib/gitlab/identifier.rb
@@ -21,10 +21,8 @@ module Gitlab
return if !commit || !commit.author_email
- email = commit.author_email
-
- identify_with_cache(:email, email) do
- User.find_by_any_email(email)
+ identify_with_cache(:email, commit.author_email) do
+ commit.author
end
end
diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6
index ee192c4f18a..4208e076e96 100644
--- a/spec/javascripts/build_spec.js.es6
+++ b/spec/javascripts/build_spec.js.es6
@@ -2,7 +2,6 @@
/* global Build */
/* global Turbolinks */
-//= require lib/utils/timeago
//= require lib/utils/datetime_utility
//= require build
//= require breakpoints
diff --git a/spec/javascripts/merge_request_widget_spec.js b/spec/javascripts/merge_request_widget_spec.js
index f38e9cb8ef5..62890f1ca96 100644
--- a/spec/javascripts/merge_request_widget_spec.js
+++ b/spec/javascripts/merge_request_widget_spec.js
@@ -1,6 +1,6 @@
/* eslint-disable space-before-function-paren, quotes, comma-dangle, dot-notation, indent, quote-props, no-var, padded-blocks, max-len */
+
/*= require merge_request_widget */
-/*= require lib/utils/timeago */
/*= require lib/utils/datetime_utility */
(function() {
diff --git a/spec/lib/gitlab/identifier_spec.rb b/spec/lib/gitlab/identifier_spec.rb
index f42c4453dd1..bb758a8a202 100644
--- a/spec/lib/gitlab/identifier_spec.rb
+++ b/spec/lib/gitlab/identifier_spec.rb
@@ -40,7 +40,7 @@ describe Gitlab::Identifier do
describe '#identify_using_commit' do
it "returns the User for an existing commit author's Email address" do
- commit = double(:commit, author_email: user.email)
+ commit = double(:commit, author: user, author_email: user.email)
expect(project).to receive(:commit).with('123').and_return(commit)
@@ -62,10 +62,9 @@ describe Gitlab::Identifier do
end
it 'caches the found users per Email' do
- commit = double(:commit, author_email: user.email)
+ commit = double(:commit, author: user, author_email: user.email)
expect(project).to receive(:commit).with('123').twice.and_return(commit)
- expect(User).to receive(:find_by_any_email).once.and_call_original
2.times do
expect(identifier.identify_using_commit(project, '123')).to eq(user)
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index f020d471422..e53ee2a4e76 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -908,6 +908,36 @@ describe API::API, api: true do
end
end
+ describe 'DELETE /projects/:id/share/:group_id' do
+ it 'returns 204 when deleting a group share' do
+ group = create(:group, :public)
+ create(:project_group_link, group: group, project: project)
+
+ delete api("/projects/#{project.id}/share/#{group.id}", user)
+
+ expect(response).to have_http_status(204)
+ expect(project.project_group_links).to be_empty
+ end
+
+ it 'returns a 400 when group id is not an integer' do
+ delete api("/projects/#{project.id}/share/foo", user)
+
+ expect(response).to have_http_status(400)
+ end
+
+ it 'returns a 404 error when group link does not exist' do
+ delete api("/projects/#{project.id}/share/1234", user)
+
+ expect(response).to have_http_status(404)
+ end
+
+ it 'returns a 404 error when project does not exist' do
+ delete api("/projects/123/share/1234", user)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
describe 'GET /projects/search/:query' do
let!(:query) { 'query'}
let!(:search) { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) }
diff --git a/spec/views/projects/edit.html.haml_spec.rb b/spec/views/projects/edit.html.haml_spec.rb
new file mode 100644
index 00000000000..d2575702ecc
--- /dev/null
+++ b/spec/views/projects/edit.html.haml_spec.rb
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe 'projects/edit' do
+ include Devise::Test::ControllerHelpers
+
+ let(:project) { create(:empty_project) }
+ let(:user) { create(:admin) }
+
+ before do
+ assign(:project, project)
+
+ allow(controller).to receive(:current_user).and_return(user)
+ allow(view).to receive_messages(current_user: user, can?: true)
+ allow(Gitlab.config.lfs).to receive(:enabled).and_return(true)
+ end
+
+ context 'LFS enabled setting' do
+ it 'displays the correct elements' do
+ render
+ expect(rendered).to have_select('project_lfs_enabled')
+ expect(rendered).to have_content('Git Large File Storage')
+ end
+ end
+end
diff --git a/app/assets/javascripts/lib/utils/timeago.js b/vendor/assets/javascripts/timeago.js
index edf0a612374..0eb6f7967a5 100644
--- a/app/assets/javascripts/lib/utils/timeago.js
+++ b/vendor/assets/javascripts/timeago.js
@@ -1,5 +1,3 @@
-/* eslint-disable no-unused-expressions, wrap-iife, func-names, curly, no-param-reassign, no-trailing-spaces, prefer-arrow-callback, no-var, one-var, quote-props, space-before-function-paren, vars-on-top, radix, prefer-template, space-infix-ops, no-use-before-define, newline-per-chained-call, no-useless-escape, no-nested-ternary, indent, no-undef, no-plusplus, one-var-declaration-per-line, operator-assignment, consistent-return, keyword-spacing, max-len, space-unary-ops, no-shadow, no-restricted-syntax, guard-for-in, eol-last, max-len */
-
/**
* Copyright (c) 2016 hustcc
* License: MIT
@@ -14,7 +12,7 @@
module.exports = factory(root);
else
root.timeago = factory(root);
-}(typeof window !== 'undefined' ? window : this,
+}(typeof window !== 'undefined' ? window : this,
function () {
var cnt = 0, // the timer counter, for timer key
indexMapEn = 'second_minute_hour_day_week_month_year'.split('_'),
@@ -32,7 +30,7 @@ function () {
SEC_ARRAY = [60, 60, 24, 7, 365/7/12, 12],
SEC_ARRAY_LEN = 6,
ATTR_DATETIME = 'datetime';
-
+
// format Date / string / timestamp to Date instance.
function toDate(input) {
if (input instanceof Date) return input;
@@ -236,4 +234,4 @@ function () {
};
return timeagoFactory;
-}); \ No newline at end of file
+});