Commit 6d4b9c45 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-04-05

# Conflicts:
#	app/models/project.rb
#	app/policies/merge_request_policy.rb
#	lib/api/helpers/projects_helpers.rb
#	lib/api/projects.rb
#	lib/gitlab/import_export/import_export.yml

[ci skip]
parents dda07ed5 6b3585d8
...@@ -19,7 +19,7 @@ export default { ...@@ -19,7 +19,7 @@ export default {
}, },
}, },
computed: { computed: {
...mapState(['leftPanelCollapsed', 'rightPanelCollapsed', 'viewer', 'delayViewerUpdated']), ...mapState(['rightPanelCollapsed', 'viewer', 'delayViewerUpdated', 'panelResizing']),
...mapGetters(['currentMergeRequest']), ...mapGetters(['currentMergeRequest']),
shouldHideEditor() { shouldHideEditor() {
return this.file && this.file.binary && !this.file.raw; return this.file && this.file.binary && !this.file.raw;
...@@ -42,15 +42,17 @@ export default { ...@@ -42,15 +42,17 @@ export default {
this.initMonaco(); this.initMonaco();
} }
}, },
leftPanelCollapsed() {
this.editor.updateDimensions();
},
rightPanelCollapsed() { rightPanelCollapsed() {
this.editor.updateDimensions(); this.editor.updateDimensions();
}, },
viewer() { viewer() {
this.createEditorInstance(); this.createEditorInstance();
}, },
panelResizing() {
if (!this.panelResizing) {
this.editor.updateDimensions();
}
},
}, },
beforeDestroy() { beforeDestroy() {
this.editor.dispose(); this.editor.dispose();
......
...@@ -69,6 +69,7 @@ export default class Editor { ...@@ -69,6 +69,7 @@ export default class Editor {
occurrencesHighlight: false, occurrencesHighlight: false,
renderLineHighlight: 'none', renderLineHighlight: 'none',
hideCursorInOverviewRuler: true, hideCursorInOverviewRuler: true,
renderSideBySide: Editor.renderSideBySide(domElement),
})), })),
); );
...@@ -81,7 +82,7 @@ export default class Editor { ...@@ -81,7 +82,7 @@ export default class Editor {
} }
attachModel(model) { attachModel(model) {
if (this.instance.getEditorType() === 'vs.editor.IDiffEditor') { if (this.isDiffEditorType) {
this.instance.setModel({ this.instance.setModel({
original: model.getOriginalModel(), original: model.getOriginalModel(),
modified: model.getModel(), modified: model.getModel(),
...@@ -153,6 +154,7 @@ export default class Editor { ...@@ -153,6 +154,7 @@ export default class Editor {
updateDimensions() { updateDimensions() {
this.instance.layout(); this.instance.layout();
this.updateDiffView();
} }
setPosition({ lineNumber, column }) { setPosition({ lineNumber, column }) {
...@@ -171,4 +173,20 @@ export default class Editor { ...@@ -171,4 +173,20 @@ export default class Editor {
this.disposable.add(this.instance.onDidChangeCursorPosition(e => cb(this.instance, e))); this.disposable.add(this.instance.onDidChangeCursorPosition(e => cb(this.instance, e)));
} }
updateDiffView() {
if (!this.isDiffEditorType) return;
this.instance.updateOptions({
renderSideBySide: Editor.renderSideBySide(this.instance.getDomNode()),
});
}
get isDiffEditorType() {
return this.instance.getEditorType() === 'vs.editor.IDiffEditor';
}
static renderSideBySide(domElement) {
return domElement.offsetWidth >= 700;
}
} }
...@@ -6,7 +6,7 @@ export const defaultEditorOptions = { ...@@ -6,7 +6,7 @@ export const defaultEditorOptions = {
minimap: { minimap: {
enabled: false, enabled: false,
}, },
wordWrap: 'bounded', wordWrap: 'on',
}; };
export default [ export default [
......
...@@ -1190,12 +1190,12 @@ export default class Notes { ...@@ -1190,12 +1190,12 @@ export default class Notes {
addForm = false; addForm = false;
let lineTypeSelector = ''; let lineTypeSelector = '';
rowCssToAdd = rowCssToAdd =
'<tr class="notes_holder js-temp-notes-holder"><td class="notes_line" colspan="2"></td><td class="notes_content"><div class="content"></div></td></tr>'; '<tr class="notes_holder js-temp-notes-holder"><td class="notes_line" colspan="2"></td><td class="notes_content"><div class="content discussion-notes"></div></td></tr>';
// In parallel view, look inside the correct left/right pane // In parallel view, look inside the correct left/right pane
if (this.isParallelView()) { if (this.isParallelView()) {
lineTypeSelector = `.${lineType}`; lineTypeSelector = `.${lineType}`;
rowCssToAdd = rowCssToAdd =
'<tr class="notes_holder js-temp-notes-holder"><td class="notes_line old"></td><td class="notes_content parallel old"><div class="content"></div></td><td class="notes_line new"></td><td class="notes_content parallel new"><div class="content"></div></td></tr>'; '<tr class="notes_holder js-temp-notes-holder"><td class="notes_line old"></td><td class="notes_content parallel old"><div class="content discussion-notes"></div></td><td class="notes_line new"></td><td class="notes_content parallel new"><div class="content discussion-notes"></div></td></tr>';
} }
const notesContentSelector = `.notes_content${lineTypeSelector} .content`; const notesContentSelector = `.notes_content${lineTypeSelector} .content`;
let notesContent = targetRow.find(notesContentSelector); let notesContent = targetRow.find(notesContentSelector);
......
...@@ -258,9 +258,7 @@ Please check your network connection and try again.`; ...@@ -258,9 +258,7 @@ Please check your network connection and try again.`;
:key="note.id" :key="note.id"
/> />
</ul> </ul>
<div <div class="discussion-reply-holder">
:class="{ 'is-replying': isReplying }"
class="discussion-reply-holder">
<template v-if="!isReplying && canReply"> <template v-if="!isReplying && canReply">
<div <div
class="btn-group-justified discussion-with-resolve-btn" class="btn-group-justified discussion-with-resolve-btn"
......
...@@ -813,6 +813,7 @@ ...@@ -813,6 +813,7 @@
} }
.discussion-notes { .discussion-notes {
padding: 0 $gl-padding $gl-padding;
min-height: 35px; min-height: 35px;
&:first-child { &:first-child {
......
...@@ -173,11 +173,7 @@ ...@@ -173,11 +173,7 @@
} }
.discussion-form { .discussion-form {
background-color: $white-light; padding-top: $gl-padding-top;
}
.discussion-form-container {
padding: $gl-padding-top $gl-padding $gl-padding;
} }
.discussion-notes .disabled-comment { .discussion-notes .disabled-comment {
...@@ -237,12 +233,7 @@ ...@@ -237,12 +233,7 @@
.discussion-body, .discussion-body,
.diff-file { .diff-file {
.discussion-reply-holder { .discussion-reply-holder {
background-color: $white-light; padding-top: $gl-padding;
padding: 10px 16px;
&.is-replying {
padding-bottom: $gl-padding;
}
} }
} }
......
...@@ -47,7 +47,7 @@ ul.notes { ...@@ -47,7 +47,7 @@ ul.notes {
} }
.timeline-entry-inner { .timeline-entry-inner {
padding: $gl-padding $gl-btn-padding; padding: $gl-padding 0;
border-bottom: 1px solid $white-normal; border-bottom: 1px solid $white-normal;
} }
...@@ -94,12 +94,6 @@ ul.notes { ...@@ -94,12 +94,6 @@ ul.notes {
} }
} }
&.note-discussion {
.timeline-entry-inner {
padding: $gl-padding 10px;
}
}
.editing-spinner { .editing-spinner {
display: none; display: none;
} }
...@@ -352,6 +346,8 @@ ul.notes { ...@@ -352,6 +346,8 @@ ul.notes {
} }
.discussion-notes { .discussion-notes {
background-color: $white-light;
&:not(:first-child) { &:not(:first-child) {
border-top: 1px solid $white-normal; border-top: 1px solid $white-normal;
margin-top: 20px; margin-top: 20px;
...@@ -363,10 +359,6 @@ ul.notes { ...@@ -363,10 +359,6 @@ ul.notes {
} }
} }
.notes {
background-color: $white-light;
}
a code { a code {
top: 0; top: 0;
margin-right: 0; margin-right: 0;
...@@ -647,8 +639,6 @@ ul.notes { ...@@ -647,8 +639,6 @@ ul.notes {
border-bottom: 1px solid $white-normal; border-bottom: 1px solid $white-normal;
.timeline-entry-inner { .timeline-entry-inner {
padding-left: $gl-padding;
padding-right: $gl-padding;
border-bottom: 0; border-bottom: 0;
} }
} }
......
...@@ -4,8 +4,8 @@ class Projects::DiscussionsController < Projects::ApplicationController ...@@ -4,8 +4,8 @@ class Projects::DiscussionsController < Projects::ApplicationController
before_action :check_merge_requests_available! before_action :check_merge_requests_available!
before_action :merge_request before_action :merge_request
before_action :discussion before_action :discussion, only: [:resolve, :unresolve]
before_action :authorize_resolve_discussion! before_action :authorize_resolve_discussion!, only: [:resolve, :unresolve]
def resolve def resolve
Discussions::ResolveService.new(project, current_user, merge_request: merge_request).execute(discussion) Discussions::ResolveService.new(project, current_user, merge_request: merge_request).execute(discussion)
......
...@@ -22,9 +22,12 @@ class Project < ActiveRecord::Base ...@@ -22,9 +22,12 @@ class Project < ActiveRecord::Base
include DeploymentPlatform include DeploymentPlatform
include ::Gitlab::Utils::StrongMemoize include ::Gitlab::Utils::StrongMemoize
include ChronicDurationAttribute include ChronicDurationAttribute
<<<<<<< HEAD
# EE specific modules # EE specific modules
prepend EE::Project prepend EE::Project
=======
>>>>>>> upstream/master
extend Gitlab::ConfigHelper extend Gitlab::ConfigHelper
......
class MergeRequestPolicy < IssuablePolicy class MergeRequestPolicy < IssuablePolicy
<<<<<<< HEAD
prepend EE::MergeRequestPolicy prepend EE::MergeRequestPolicy
=======
>>>>>>> upstream/master
end end
...@@ -24,21 +24,20 @@ ...@@ -24,21 +24,20 @@
-# DiffNote -# DiffNote
= f.hidden_field :position = f.hidden_field :position
.discussion-form-container = render layout: 'projects/md_preview', locals: { url: preview_url, referenced_users: true } do
= render layout: 'projects/md_preview', locals: { url: preview_url, referenced_users: true } do = render 'projects/zen', f: f,
= render 'projects/zen', f: f, attr: :note,
attr: :note, classes: 'note-textarea js-note-text',
classes: 'note-textarea js-note-text', placeholder: "Write a comment or drag your files here...",
placeholder: "Write a comment or drag your files here...", supports_quick_actions: supports_quick_actions,
supports_quick_actions: supports_quick_actions, supports_autocomplete: supports_autocomplete
supports_autocomplete: supports_autocomplete = render 'shared/notes/hints', supports_quick_actions: supports_quick_actions
= render 'shared/notes/hints', supports_quick_actions: supports_quick_actions .error-alert
.error-alert
.note-form-actions.clearfix
.note-form-actions.clearfix = render partial: 'shared/notes/comment_button'
= render partial: 'shared/notes/comment_button'
= yield(:note_actions)
= yield(:note_actions)
%a.btn.btn-cancel.js-note-discard{ role: "button", data: {cancel_text: "Cancel" } }
%a.btn.btn-cancel.js-note-discard{ role: "button", data: {cancel_text: "Cancel" } } Discard draft
Discard draft
---
title: Refactor and tweak margin for note forms on Issuable
merge_request: 18120
author: Takuya Noguchi
type: fixed
---
title: Adjust 404's for LegacyDiffNote discussion rendering
merge_request: 18201
author:
type: fixed
...@@ -539,6 +539,8 @@ Example response: ...@@ -539,6 +539,8 @@ Example response:
## List Merge Requests associated with a commit ## List Merge Requests associated with a commit
> [Introduced][ce-18004] in GitLab 10.7.
Get a list of Merge Requests related to the specified commit. Get a list of Merge Requests related to the specified commit.
``` ```
...@@ -608,3 +610,4 @@ Example response: ...@@ -608,3 +610,4 @@ Example response:
[ce-6096]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6096 "Multi-file commit" [ce-6096]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6096 "Multi-file commit"
[ce-8047]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8047 [ce-8047]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8047
[ce-15026]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15026 [ce-15026]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15026
[ce-18004]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18004
...@@ -28,6 +28,7 @@ module API ...@@ -28,6 +28,7 @@ module API
optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests' optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests'
end end
<<<<<<< HEAD
params :optional_project_params_ee do params :optional_project_params_ee do
optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins' optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins'
optional :approvals_before_merge, type: Integer, desc: 'How many approvers should approve merge request by default' optional :approvals_before_merge, type: Integer, desc: 'How many approvers should approve merge request by default'
...@@ -37,6 +38,10 @@ module API ...@@ -37,6 +38,10 @@ module API
params :optional_project_params do params :optional_project_params do
use :optional_project_params_ce use :optional_project_params_ce
use :optional_project_params_ee use :optional_project_params_ee
=======
params :optional_project_params do
use :optional_project_params_ce
>>>>>>> upstream/master
end end
end end
end end
......
...@@ -267,6 +267,7 @@ module API ...@@ -267,6 +267,7 @@ module API
optional :default_branch, type: String, desc: 'The default branch of the project' optional :default_branch, type: String, desc: 'The default branch of the project'
optional :path, type: String, desc: 'The path of the repository' optional :path, type: String, desc: 'The path of the repository'
<<<<<<< HEAD
# EE # EE
at_least_one_of_ee = [ at_least_one_of_ee = [
:approvals_before_merge, :approvals_before_merge,
...@@ -276,6 +277,10 @@ module API ...@@ -276,6 +277,10 @@ module API
use :optional_project_params use :optional_project_params
at_least_one_of(*(at_least_one_of_ce + at_least_one_of_ee)) at_least_one_of(*(at_least_one_of_ce + at_least_one_of_ee))
=======
use :optional_project_params
at_least_one_of(*at_least_one_of_ce)
>>>>>>> upstream/master
end end
put ':id' do put ':id' do
authorize_admin_project authorize_admin_project
......
...@@ -110,10 +110,13 @@ excluded_attributes: ...@@ -110,10 +110,13 @@ excluded_attributes:
- :mirror_user_id - :mirror_user_id
- :mirror_trigger_builds - :mirror_trigger_builds
- :storage_version - :storage_version
<<<<<<< HEAD
- :remote_mirror_available_overridden - :remote_mirror_available_overridden
- :only_mirror_protected_branches - :only_mirror_protected_branches
- :pull_mirror_available_overridden - :pull_mirror_available_overridden
- :mirror_overwrites_diverged_branches - :mirror_overwrites_diverged_branches
=======
>>>>>>> upstream/master
- :description_html - :description_html
snippets: snippets:
- :expired_at - :expired_at
......
...@@ -16,6 +16,53 @@ describe Projects::DiscussionsController do ...@@ -16,6 +16,53 @@ describe Projects::DiscussionsController do
} }
end end
describe 'GET show' do
before do
sign_in user
end
context 'when user is not authorized to read the MR' do
it 'returns 404' do
get :show, request_params, format: :json
expect(response).to have_gitlab_http_status(404)
end
end
context 'when user is authorized to read the MR' do
before do
project.add_reporter(user)
end
it 'returns status 200' do
get :show, request_params, format: :json
expect(response).to have_gitlab_http_status(200)
end
it 'returns status 404 if MR does not exists' do
merge_request.destroy!
get :show, request_params, format: :json
expect(response).to have_gitlab_http_status(404)
end
end
context 'when user is authorized but note is LegacyDiffNote' do
before do
project.add_developer(user)
note.update!(type: 'LegacyDiffNote')
end
it 'returns status 200' do
get :show, request_params, format: :json
expect(response).to have_gitlab_http_status(200)
end
end
end
describe 'POST resolve' do describe 'POST resolve' do
before do before do
sign_in user sign_in user
......
...@@ -199,47 +199,49 @@ describe('RepoEditor', () => { ...@@ -199,47 +199,49 @@ describe('RepoEditor', () => {
}); });
}); });
describe('setup editor for merge request viewing', () => { describe('editor updateDimensions', () => {
beforeEach(done => { beforeEach(() => {
// Resetting as the main test setup has already done it spyOn(vm.editor, 'updateDimensions').and.callThrough();
vm.$destroy(); spyOn(vm.editor, 'updateDiffView');
resetStore(vm.$store); });
Editor.editorInstance.modelManager.dispose();
const f = {
...file(),
active: true,
tempFile: true,
html: 'testing',
mrChange: { diff: 'ABC' },
baseRaw: 'testing',
content: 'test',
};
const RepoEditor = Vue.extend(repoEditor);
vm = createComponentWithStore(RepoEditor, store, {
file: f,
});
vm.$store.state.openFiles.push(f); it('calls updateDimensions when rightPanelCollapsed is changed', done => {
vm.$store.state.entries[f.path] = f; vm.$store.state.rightPanelCollapsed = true;
vm.$store.state.viewer = 'mrdiff'; vm.$nextTick(() => {
expect(vm.editor.updateDimensions).toHaveBeenCalled();
expect(vm.editor.updateDiffView).toHaveBeenCalled();
vm.monaco = true; done();
});
});
vm.$mount(); it('calls updateDimensions when panelResizing is false', done => {
vm.$store.state.panelResizing = true;
monacoLoader(['vs/editor/editor.main'], () => { vm
setTimeout(done, 0); .$nextTick()
}); .then(() => {
vm.$store.state.panelResizing = false;
})
.then(vm.$nextTick)
.then(() => {
expect(vm.editor.updateDimensions).toHaveBeenCalled();
expect(vm.editor.updateDiffView).toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
}); });
it('attaches merge request model to editor when merge request diff', () => { it('does not call updateDimensions when panelResizing is true', done => {
spyOn(vm.editor, 'attachMergeRequestModel').and.callThrough(); vm.$store.state.panelResizing = true;
vm.setupEditor(); vm.$nextTick(() => {
expect(vm.editor.updateDimensions).not.toHaveBeenCalled();
expect(vm.editor.updateDiffView).not.toHaveBeenCalled();
expect(vm.editor.attachMergeRequestModel).toHaveBeenCalledWith(vm.model); done();
});
}); });
}); });
}); });
...@@ -76,7 +76,8 @@ describe('Multi-file editor library', () => { ...@@ -76,7 +76,8 @@ describe('Multi-file editor library', () => {
occurrencesHighlight: false, occurrencesHighlight: false,
renderLineHighlight: 'none', renderLineHighlight: 'none',
hideCursorInOverviewRuler: true, hideCursorInOverviewRuler: true,
wordWrap: 'bounded', wordWrap: 'on',
renderSideBySide: true,
}); });
}); });
}); });
...@@ -215,4 +216,56 @@ describe('Multi-file editor library', () => { ...@@ -215,4 +216,56 @@ describe('Multi-file editor library', () => {
expect(instance.decorationsController.dispose).not.toHaveBeenCalled(); expect(instance.decorationsController.dispose).not.toHaveBeenCalled();
}); });
}); });
describe('updateDiffView', () => {
describe('edit mode', () => {
it('does not update options', () => {
instance.createInstance(holder);
spyOn(instance.instance, 'updateOptions');
instance.updateDiffView();
expect(instance.instance.updateOptions).not.toHaveBeenCalled();
});
});
describe('diff mode', () => {
beforeEach(() => {
instance.createDiffInstance(holder);
spyOn(instance.instance, 'updateOptions').and.callThrough();
});
it('sets renderSideBySide to false if el is less than 700 pixels', () => {
spyOnProperty(instance.instance.getDomNode(), 'offsetWidth').and.returnValue(600);
expect(instance.instance.updateOptions).not.toHaveBeenCalledWith({
renderSideBySide: false,
});
});
it('sets renderSideBySide to false if el is more than 700 pixels', () => {
spyOnProperty(instance.instance.getDomNode(), 'offsetWidth').and.returnValue(800);
expect(instance.instance.updateOptions).not.toHaveBeenCalledWith({
renderSideBySide: true,
});
});
});
});
describe('isDiffEditorType', () => {
it('returns true when diff editor', () => {
instance.createDiffInstance(holder);
expect(instance.isDiffEditorType).toBe(true);
});
it('returns false when not diff editor', () => {
instance.createInstance(holder);
expect(instance.isDiffEditorType).toBe(false);
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment