...@@ -59,6 +59,7 @@ eslint-report.html ...@@ -59,6 +59,7 @@ eslint-report.html
/public/uploads.* /public/uploads.*
/public/uploads/ /public/uploads/
/shared/artifacts/ /shared/artifacts/
/spec/examples.txt
/rails_best_practices_output.html /rails_best_practices_output.html
/tags /tags
/vendor/bundle/* /vendor/bundle/*
... ...
......
...@@ -66,3 +66,4 @@ schedule:package-and-qa: ...@@ -66,3 +66,4 @@ schedule:package-and-qa:
- .default-only - .default-only
- .only:variables_refs-canonical-dot-com-schedules - .only:variables_refs-canonical-dot-com-schedules
needs: ["build-qa-image", "gitlab:assets:compile pull-cache"] needs: ["build-qa-image", "gitlab:assets:compile pull-cache"]
allow_failure: true
...@@ -64,7 +64,7 @@ gem 'u2f', '~> 0.2.1' ...@@ -64,7 +64,7 @@ gem 'u2f', '~> 0.2.1'
# GitLab Pages # GitLab Pages
gem 'validates_hostname', '~> 1.0.6' gem 'validates_hostname', '~> 1.0.6'
gem 'rubyzip', '~> 1.2.2', require: 'zip' gem 'rubyzip', '~> 1.3.0', require: 'zip'
# GitLab Pages letsencrypt support # GitLab Pages letsencrypt support
gem 'acme-client', '~> 2.0.2' gem 'acme-client', '~> 2.0.2'
...@@ -72,7 +72,7 @@ gem 'acme-client', '~> 2.0.2' ...@@ -72,7 +72,7 @@ gem 'acme-client', '~> 2.0.2'
gem 'browser', '~> 2.5' gem 'browser', '~> 2.5'
# GPG # GPG
gem 'gpgme', '~> 2.0.18' gem 'gpgme', '~> 2.0.19'
# LDAP Auth # LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes # GitLab fork with several improvements to original library. For full list of changes
...@@ -151,7 +151,7 @@ gem 'asciidoctor-plantuml', '0.0.9' ...@@ -151,7 +151,7 @@ gem 'asciidoctor-plantuml', '0.0.9'
gem 'rouge', '~> 3.11.0' gem 'rouge', '~> 3.11.0'
gem 'truncato', '~> 0.7.11' gem 'truncato', '~> 0.7.11'
gem 'bootstrap_form', '~> 4.2.0' gem 'bootstrap_form', '~> 4.2.0'
gem 'nokogiri', '~> 1.10.4' gem 'nokogiri', '~> 1.10.5'
gem 'escape_utils', '~> 1.1' gem 'escape_utils', '~> 1.1'
# Calendar rendering # Calendar rendering
... ...
......
...@@ -411,7 +411,7 @@ GEM ...@@ -411,7 +411,7 @@ GEM
multi_json (~> 1.11) multi_json (~> 1.11)
os (>= 0.9, < 2.0) os (>= 0.9, < 2.0)
signet (~> 0.7) signet (~> 0.7)
gpgme (2.0.18) gpgme (2.0.19)
mini_portile2 (~> 2.3) mini_portile2 (~> 2.3)
grape (1.1.0) grape (1.1.0)
activesupport activesupport
...@@ -902,7 +902,7 @@ GEM ...@@ -902,7 +902,7 @@ GEM
sexp_processor (~> 4.9) sexp_processor (~> 4.9)
rubyntlm (0.6.2) rubyntlm (0.6.2)
rubypants (0.2.0) rubypants (0.2.0)
rubyzip (1.2.2) rubyzip (1.3.0)
rugged (0.28.3.1) rugged (0.28.3.1)
safe_yaml (1.0.4) safe_yaml (1.0.4)
sanitize (4.6.6) sanitize (4.6.6)
...@@ -1183,7 +1183,7 @@ DEPENDENCIES ...@@ -1183,7 +1183,7 @@ DEPENDENCIES
gon (~> 6.2) gon (~> 6.2)
google-api-client (~> 0.23) google-api-client (~> 0.23)
google-protobuf (~> 3.8.0) google-protobuf (~> 3.8.0)
gpgme (~> 2.0.18) gpgme (~> 2.0.19)
grape (~> 1.1.0) grape (~> 1.1.0)
grape-entity (~> 0.7.1) grape-entity (~> 0.7.1)
grape-path-helpers (~> 1.1) grape-path-helpers (~> 1.1)
...@@ -1227,7 +1227,7 @@ DEPENDENCIES ...@@ -1227,7 +1227,7 @@ DEPENDENCIES
net-ldap net-ldap
net-ntp net-ntp
net-ssh (~> 5.2) net-ssh (~> 5.2)
nokogiri (~> 1.10.4) nokogiri (~> 1.10.5)
oauth2 (~> 1.4) oauth2 (~> 1.4)
octokit (~> 4.9) octokit (~> 4.9)
omniauth (~> 1.8) omniauth (~> 1.8)
...@@ -1293,7 +1293,7 @@ DEPENDENCIES ...@@ -1293,7 +1293,7 @@ DEPENDENCIES
ruby-prof (~> 1.0.0) ruby-prof (~> 1.0.0)
ruby-progressbar ruby-progressbar
ruby_parser (~> 3.8) ruby_parser (~> 3.8)
rubyzip (~> 1.2.2) rubyzip (~> 1.3.0)
rugged (~> 0.28) rugged (~> 0.28)
sanitize (~> 4.6) sanitize (~> 4.6)
sassc-rails (~> 2.1.0) sassc-rails (~> 2.1.0)
... ...
......
...@@ -54,6 +54,11 @@ export default { ...@@ -54,6 +54,11 @@ export default {
}, },
}, },
computed: { computed: {
milestoneLink() {
const { title } = this.issuable.milestone;
return this.issuableLink({ milestone_title: title });
},
hasLabels() { hasLabels() {
return Boolean(this.issuable.labels && this.issuable.labels.length); return Boolean(this.issuable.labels && this.issuable.labels.length);
}, },
...@@ -167,8 +172,11 @@ export default { ...@@ -167,8 +172,11 @@ export default {
color: label.text_color, color: label.text_color,
}; };
}, },
issuableLink(params) {
return mergeUrlParams(params, this.baseUrl);
},
labelHref({ name }) { labelHref({ name }) {
return mergeUrlParams({ 'label_name[]': name }, this.baseUrl); return this.issuableLink({ 'label_name[]': name });
}, },
onSelect(ev) { onSelect(ev) {
this.$emit('select', { this.$emit('select', {
...@@ -216,9 +224,9 @@ export default { ...@@ -216,9 +224,9 @@ export default {
></i> ></i>
<gl-link :href="issuable.web_url">{{ issuable.title }}</gl-link> <gl-link :href="issuable.web_url">{{ issuable.title }}</gl-link>
</span> </span>
<span v-if="issuable.has_tasks" class="ml-1 task-status d-none d-sm-inline-block"> <span v-if="issuable.has_tasks" class="ml-1 task-status d-none d-sm-inline-block">{{
{{ issuable.task_status }} issuable.task_status
</span> }}</span>
</div> </div>
<div class="issuable-info"> <div class="issuable-info">
...@@ -233,7 +241,7 @@ export default { ...@@ -233,7 +241,7 @@ export default {
v-if="issuable.milestone" v-if="issuable.milestone"
v-gl-tooltip v-gl-tooltip
class="d-none d-sm-inline-block mr-1 js-milestone" class="d-none d-sm-inline-block mr-1 js-milestone"
:href="issuable.milestone.web_url" :href="milestoneLink"
:title="milestoneTooltipText" :title="milestoneTooltipText"
> >
<i class="fa fa-clock-o"></i> <i class="fa fa-clock-o"></i>
... ...
......
/* eslint-disable no-useless-escape, no-var, no-underscore-dangle, func-names, no-return-assign, one-var, consistent-return, class-methods-use-this */ /* eslint-disable no-useless-escape, no-underscore-dangle, func-names, no-return-assign, consistent-return, class-methods-use-this */
import $ from 'jquery'; import $ from 'jquery';
import 'cropper'; import 'cropper';
...@@ -59,8 +59,7 @@ import _ from 'underscore'; ...@@ -59,8 +59,7 @@ import _ from 'underscore';
} }
bindEvents() { bindEvents() {
var _this; const _this = this;
_this = this;
this.fileInput.on('change', function(e) { this.fileInput.on('change', function(e) {
_this.onFileInputChange(e, this); _this.onFileInputChange(e, this);
this.value = null; this.value = null;
...@@ -70,8 +69,7 @@ import _ from 'underscore'; ...@@ -70,8 +69,7 @@ import _ from 'underscore';
this.modalCrop.on('hidden.bs.modal', this.onModalHide); this.modalCrop.on('hidden.bs.modal', this.onModalHide);
this.uploadImageBtn.on('click', this.onUploadImageBtnClick); this.uploadImageBtn.on('click', this.onUploadImageBtnClick);
this.cropActionsBtn.on('click', function() { this.cropActionsBtn.on('click', function() {
var btn; const btn = this;
btn = this;
return _this.onActionBtnClick(btn); return _this.onActionBtnClick(btn);
}); });
return (this.croppedImageBlob = null); return (this.croppedImageBlob = null);
...@@ -82,8 +80,7 @@ import _ from 'underscore'; ...@@ -82,8 +80,7 @@ import _ from 'underscore';
} }
onModalShow() { onModalShow() {
var _this; const _this = this;
_this = this;
return this.modalCropImg.cropper({ return this.modalCropImg.cropper({
viewMode: 1, viewMode: 1,
center: false, center: false,
...@@ -128,8 +125,7 @@ import _ from 'underscore'; ...@@ -128,8 +125,7 @@ import _ from 'underscore';
} }
onActionBtnClick(btn) { onActionBtnClick(btn) {
var data; const data = $(btn).data();
data = $(btn).data();
if (this.modalCropImg.data('cropper') && data.method) { if (this.modalCropImg.data('cropper') && data.method) {
return this.modalCropImg.cropper(data.method, data.option); return this.modalCropImg.cropper(data.method, data.option);
} }
...@@ -140,9 +136,8 @@ import _ from 'underscore'; ...@@ -140,9 +136,8 @@ import _ from 'underscore';
} }
readFile(input) { readFile(input) {
var _this, reader; const _this = this;
_this = this; const reader = new FileReader();
reader = new FileReader();
reader.onload = () => { reader.onload = () => {
_this.modalCropImg.attr('src', reader.result); _this.modalCropImg.attr('src', reader.result);
return _this.modalCrop.modal('show'); return _this.modalCrop.modal('show');
...@@ -151,9 +146,10 @@ import _ from 'underscore'; ...@@ -151,9 +146,10 @@ import _ from 'underscore';
} }
dataURLtoBlob(dataURL) { dataURLtoBlob(dataURL) {
var array, binary, i, len; let i = 0;
binary = atob(dataURL.split(',')[1]); let len = 0;
array = []; const binary = atob(dataURL.split(',')[1]);
const array = [];
for (i = 0, len = binary.length; i < len; i += 1) { for (i = 0, len = binary.length; i < len; i += 1) {
array.push(binary.charCodeAt(i)); array.push(binary.charCodeAt(i));
...@@ -164,9 +160,8 @@ import _ from 'underscore'; ...@@ -164,9 +160,8 @@ import _ from 'underscore';
} }
setPreview() { setPreview() {
var filename; const filename = this.fileInput.val().replace(FILENAMEREGEX, '');
this.previewImage.attr('src', this.dataURL); this.previewImage.attr('src', this.dataURL);
filename = this.fileInput.val().replace(FILENAMEREGEX, '');
return this.filename.text(filename); return this.filename.text(filename);
} }
... ...
......
...@@ -33,6 +33,8 @@ export default { ...@@ -33,6 +33,8 @@ export default {
<div class="block subscriptions"> <div class="block subscriptions">
<subscriptions <subscriptions
:loading="store.isFetching.subscriptions" :loading="store.isFetching.subscriptions"
:project-emails-disabled="store.projectEmailsDisabled"
:subscribe-disabled-description="store.subscribeDisabledDescription"
:subscribed="store.subscribed" :subscribed="store.subscribed"
@toggleSubscription="onToggleSubscription" @toggleSubscription="onToggleSubscription"
/> />
... ...
......
...@@ -26,6 +26,16 @@ export default { ...@@ -26,6 +26,16 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
projectEmailsDisabled: {
type: Boolean,
required: false,
default: false,
},
subscribeDisabledDescription: {
type: String,
required: false,
default: '',
},
subscribed: { subscribed: {
type: Boolean, type: Boolean,
required: false, required: false,
...@@ -42,11 +52,23 @@ export default { ...@@ -42,11 +52,23 @@ export default {
return this.subscribed === null; return this.subscribed === null;
}, },
notificationIcon() { notificationIcon() {
if (this.projectEmailsDisabled) {
return ICON_OFF;
}
return this.subscribed ? ICON_ON : ICON_OFF; return this.subscribed ? ICON_ON : ICON_OFF;
}, },
notificationTooltip() { notificationTooltip() {
if (this.projectEmailsDisabled) {
return this.subscribeDisabledDescription;
}
return this.subscribed ? LABEL_ON : LABEL_OFF; return this.subscribed ? LABEL_ON : LABEL_OFF;
}, },
notificationText() {
if (this.projectEmailsDisabled) {
return this.subscribeDisabledDescription;
}
return __('Notifications');
},
}, },
methods: { methods: {
/** /**
...@@ -81,6 +103,7 @@ export default { ...@@ -81,6 +103,7 @@ export default {
<template> <template>
<div> <div>
<span <span
ref="tooltip"
v-tooltip v-tooltip
class="sidebar-collapsed-icon" class="sidebar-collapsed-icon"
:title="notificationTooltip" :title="notificationTooltip"
...@@ -96,8 +119,9 @@ export default { ...@@ -96,8 +119,9 @@ export default {
class="sidebar-item-icon is-active" class="sidebar-item-icon is-active"
/> />
</span> </span>
<span class="issuable-header-text hide-collapsed float-left"> {{ __('Notifications') }} </span> <span class="issuable-header-text hide-collapsed float-left"> {{ notificationText }} </span>
<toggle-button <toggle-button
v-if="!projectEmailsDisabled"
ref="toggleButton" ref="toggleButton"
:is-loading="showLoadingState" :is-loading="showLoadingState"
:value="subscribed" :value="subscribed"
... ...
......
...@@ -28,6 +28,8 @@ export default class SidebarStore { ...@@ -28,6 +28,8 @@ export default class SidebarStore {
this.moveToProjectId = 0; this.moveToProjectId = 0;
this.isLockDialogOpen = false; this.isLockDialogOpen = false;
this.participants = []; this.participants = [];
this.projectEmailsDisabled = false;
this.subscribeDisabledDescription = '';
this.subscribed = null; this.subscribed = null;
SidebarStore.singleton = this; SidebarStore.singleton = this;
...@@ -53,6 +55,8 @@ export default class SidebarStore { ...@@ -53,6 +55,8 @@ export default class SidebarStore {
} }
setSubscriptionsData(data) { setSubscriptionsData(data) {
this.projectEmailsDisabled = data.project_emails_disabled || false;
this.subscribeDisabledDescription = data.subscribe_disabled_description;
this.isFetching.subscriptions = false; this.isFetching.subscriptions = false;
this.subscribed = data.subscribed || false; this.subscribed = data.subscribed || false;
} }
... ...
......
...@@ -20,11 +20,11 @@ class ApplicationController < ActionController::Base ...@@ -20,11 +20,11 @@ class ApplicationController < ActionController::Base
before_action :authenticate_user!, except: [:route_not_found] before_action :authenticate_user!, except: [:route_not_found]
before_action :enforce_terms!, if: :should_enforce_terms? before_action :enforce_terms!, if: :should_enforce_terms?
before_action :validate_user_service_ticket! before_action :validate_user_service_ticket!
before_action :check_password_expiration, if: :html_request? before_action :check_password_expiration
before_action :ldap_security_check before_action :ldap_security_check
before_action :sentry_context before_action :sentry_context
before_action :default_headers before_action :default_headers
before_action :add_gon_variables, if: :html_request? before_action :add_gon_variables, unless: [:peek_request?, :json_request?]
before_action :configure_permitted_parameters, if: :devise_controller? before_action :configure_permitted_parameters, if: :devise_controller?
before_action :require_email, unless: :devise_controller? before_action :require_email, unless: :devise_controller?
before_action :active_user_check, unless: :devise_controller? before_action :active_user_check, unless: :devise_controller?
...@@ -455,8 +455,8 @@ class ApplicationController < ActionController::Base ...@@ -455,8 +455,8 @@ class ApplicationController < ActionController::Base
response.headers['Page-Title'] = URI.escape(page_title('GitLab')) response.headers['Page-Title'] = URI.escape(page_title('GitLab'))
end end
def html_request? def peek_request?
request.format.html? request.path.start_with?('/-/peek')
end end
def json_request? def json_request?
...@@ -466,7 +466,7 @@ class ApplicationController < ActionController::Base ...@@ -466,7 +466,7 @@ class ApplicationController < ActionController::Base
def should_enforce_terms? def should_enforce_terms?
return false unless Gitlab::CurrentSettings.current_application_settings.enforce_terms return false unless Gitlab::CurrentSettings.current_application_settings.enforce_terms
html_request? && !devise_controller? !(peek_request? || devise_controller?)
end end
def set_usage_stats_consent_flag def set_usage_stats_consent_flag
... ...
......
...@@ -4,18 +4,15 @@ module ConfirmEmailWarning ...@@ -4,18 +4,15 @@ module ConfirmEmailWarning
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
before_action :set_confirm_warning, if: :show_confirm_warning? before_action :set_confirm_warning, if: -> { Feature.enabled?(:soft_email_confirmation) }
end end
protected protected
def show_confirm_warning?
html_request? && request.get? && Feature.enabled?(:soft_email_confirmation)
end
def set_confirm_warning def set_confirm_warning
return unless current_user return unless current_user
return if current_user.confirmed? return if current_user.confirmed?
return if peek_request? || json_request? || !request.get?
email = current_user.unconfirmed_email || current_user.email email = current_user.unconfirmed_email || current_user.email
... ...
......
...@@ -4,7 +4,7 @@ module SourcegraphGon ...@@ -4,7 +4,7 @@ module SourcegraphGon
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
before_action :push_sourcegraph_gon, if: :html_request? before_action :push_sourcegraph_gon, unless: :json_request?
end end
private private
... ...
......
# frozen_string_literal: true # frozen_string_literal: true
module UploadsActions module UploadsActions
extend ActiveSupport::Concern
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
include SendFileUpload include SendFileUpload
UPLOAD_MOUNTS = %w(avatar attachment file logo header_logo favicon).freeze UPLOAD_MOUNTS = %w(avatar attachment file logo header_logo favicon).freeze
included do
prepend_before_action :set_request_format_from_path_extension
end
def create def create
uploader = UploadService.new(model, params[:file], uploader_class).execute uploader = UploadService.new(model, params[:file], uploader_class).execute
...@@ -69,18 +64,6 @@ module UploadsActions ...@@ -69,18 +64,6 @@ module UploadsActions
private private
# From ActionDispatch::Http::MimeNegotiation. We have an initializer that
# monkey-patches this method out (so that repository paths don't guess a
# format based on extension), but we do want this behaviour when serving
# uploads.
def set_request_format_from_path_extension
path = request.headers['action_dispatch.original_path'] || request.headers['PATH_INFO']
if match = path&.match(/\.(\w+)\z/)
request.format = match.captures.first
end
end
def uploader_class def uploader_class
raise NotImplementedError raise NotImplementedError
end end
... ...
......
...@@ -4,6 +4,9 @@ class Environment < ApplicationRecord ...@@ -4,6 +4,9 @@ class Environment < ApplicationRecord
include Gitlab::Utils::StrongMemoize include Gitlab::Utils::StrongMemoize
include ReactiveCaching include ReactiveCaching
self.reactive_cache_refresh_interval = 1.minute
self.reactive_cache_lifetime = 55.seconds
belongs_to :project, required: true belongs_to :project, required: true
has_many :deployments, -> { visible }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :deployments, -> { visible }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
... ...
......
...@@ -3,11 +3,20 @@ ...@@ -3,11 +3,20 @@
class IssuableSidebarExtrasEntity < Grape::Entity class IssuableSidebarExtrasEntity < Grape::Entity
include RequestAwareEntity include RequestAwareEntity
include TimeTrackableEntity include TimeTrackableEntity
include NotificationsHelper
expose :participants, using: ::API::Entities::UserBasic do |issuable| expose :participants, using: ::API::Entities::UserBasic do |issuable|
issuable.participants(request.current_user) issuable.participants(request.current_user)
end end
expose :project_emails_disabled do |issuable|
issuable.project.emails_disabled?
end
expose :subscribe_disabled_description do |issuable|
notification_description(:owner_disabled)
end
expose :subscribed do |issuable| expose :subscribed do |issuable|
issuable.subscribed?(request.current_user, issuable.project) issuable.subscribed?(request.current_user, issuable.project)
end end
... ...
......
...@@ -11,19 +11,21 @@ module MergeRequests ...@@ -11,19 +11,21 @@ module MergeRequests
private private
def commit def commit
repository.ff_merge(current_user, ff_merge = repository.ff_merge(current_user,
source, source,
merge_request.target_branch, merge_request.target_branch,
merge_request: merge_request) merge_request: merge_request)
if merge_request.squash
merge_request.update_column(:squash_commit_sha, merge_request.in_progress_merge_commit_sha)
end
ff_merge
rescue Gitlab::Git::PreReceiveError => e rescue Gitlab::Git::PreReceiveError => e
raise MergeError, e.message raise MergeError, e.message
rescue StandardError => e rescue StandardError => e
raise MergeError, "Something went wrong during merge: #{e.message}" raise MergeError, "Something went wrong during merge: #{e.message}"
ensure ensure
if merge_request.squash
merge_request.update_column(:squash_commit_sha, merge_request.in_progress_merge_commit_sha)
end
merge_request.update(in_progress_merge_commit_sha: nil) merge_request.update(in_progress_merge_commit_sha: nil)
end end
end end
... ...
......
...@@ -141,13 +141,7 @@ ...@@ -141,13 +141,7 @@
.js-sidebar-participants-entry-point .js-sidebar-participants-entry-point
- if signed_in - if signed_in
- if issuable_sidebar[:project_emails_disabled] .js-sidebar-subscriptions-entry-point
.block.js-emails-disabled
.sidebar-collapsed-icon.has-tooltip{ title: notification_description(:owner_disabled), data: { placement: "left", container: "body", boundary: 'viewport' } }
= notification_setting_icon
.hide-collapsed= notification_description(:owner_disabled)
- else
.js-sidebar-subscriptions-entry-point
- project_ref = issuable_sidebar[:reference] - project_ref = issuable_sidebar[:reference]
.block.project-reference .block.project-reference
... ...
......
---
title: Refactor disabled sidebar notifications to Vue
merge_request: 20007
author: minghuan lei
type: other
---
title: Update the DB schema to allow linking between Vulnerabilities and Issues
merge_request: 19852
author:
type: added
---
title: Adds a copy button next to package metadata on the details page
merge_request: 19881
author:
type: added