Skip to content
Snippets Groups Projects
Unverified Commit b6ff7958 authored by John T Skarbek's avatar John T Skarbek
Browse files

Merge commit 'b99b6bb0' into 11-10-stable

parents 7de4c893 b99b6bb0
No related branches found
No related tags found
No related merge requests found
Showing
with 181 additions and 105 deletions
Loading
Loading
@@ -852,8 +852,6 @@ qa:selectors:
.qa-frontend-node: &qa-frontend-node
<<: *dedicated-no-docs-no-db-pull-cache-job
stage: test
variables:
NODE_OPTIONS: --max_old_space_size=3584
cache:
key: "$CI_JOB_NAME"
paths:
Loading
Loading
@@ -1143,3 +1141,4 @@ schedule:review-performance:
<<: *review-schedules-only
script:
- wait_for_job_to_be_done "schedule:review-deploy"
danger.import_plugin('danger/plugins/helper.rb')
danger.import_dangerfile(path: 'danger/metadata')
danger.import_dangerfile(path: 'danger/changes_size')
danger.import_dangerfile(path: 'danger/changelog')
danger.import_dangerfile(path: 'danger/specs')
danger.import_dangerfile(path: 'danger/gemfile')
danger.import_dangerfile(path: 'danger/database')
danger.import_dangerfile(path: 'danger/documentation')
danger.import_dangerfile(path: 'danger/frozen_string')
danger.import_dangerfile(path: 'danger/commit_messages')
danger.import_dangerfile(path: 'danger/duplicate_yarn_dependencies')
danger.import_dangerfile(path: 'danger/prettier')
danger.import_dangerfile(path: 'danger/eslint')
danger.import_dangerfile(path: 'danger/roulette')
danger.import_dangerfile(path: 'danger/single_codebase')
danger.import_dangerfile(path: 'danger/gitlab_ui_wg')
unless helper.release_automation?
danger.import_dangerfile(path: 'danger/metadata')
danger.import_dangerfile(path: 'danger/changes_size')
danger.import_dangerfile(path: 'danger/changelog')
danger.import_dangerfile(path: 'danger/specs')
danger.import_dangerfile(path: 'danger/gemfile')
danger.import_dangerfile(path: 'danger/database')
danger.import_dangerfile(path: 'danger/documentation')
danger.import_dangerfile(path: 'danger/frozen_string')
danger.import_dangerfile(path: 'danger/commit_messages')
danger.import_dangerfile(path: 'danger/duplicate_yarn_dependencies')
danger.import_dangerfile(path: 'danger/prettier')
danger.import_dangerfile(path: 'danger/eslint')
danger.import_dangerfile(path: 'danger/roulette')
danger.import_dangerfile(path: 'danger/single_codebase')
danger.import_dangerfile(path: 'danger/gitlab_ui_wg')
end
Loading
Loading
@@ -48,10 +48,13 @@ export default {
noteableType: this.noteableType,
noteTargetLine: this.noteTargetLine,
diffViewType: this.diffViewType,
diffFile: this.getDiffFileByHash(this.diffFileHash),
diffFile: this.diffFile,
linePosition: this.linePosition,
};
},
diffFile() {
return this.getDiffFileByHash(this.diffFileHash);
},
},
mounted() {
if (this.isLoggedIn) {
Loading
Loading
@@ -102,6 +105,7 @@ export default {
:line-code="line.line_code"
:line="line"
:help-page-path="helpPagePath"
:diff-file="diffFile"
save-button-title="Comment"
class="diff-comment-form"
@handleFormUpdateAddToReview="addToReview"
Loading
Loading
Loading
Loading
@@ -61,6 +61,11 @@ export default {
required: false,
default: null,
},
diffFile: {
type: Object,
required: false,
default: null,
},
helpPagePath: {
type: String,
required: false,
Loading
Loading
@@ -102,9 +107,42 @@ export default {
}
return '#';
},
diffParams() {
if (this.diffFile) {
return {
filePath: this.diffFile.file_path,
refs: this.diffFile.diff_refs,
};
} else if (this.note && this.note.position) {
return {
filePath: this.note.position.new_path,
refs: this.note.position,
};
} else if (this.discussion && this.discussion.diff_file) {
return {
filePath: this.discussion.diff_file.file_path,
refs: this.discussion.diff_file.diff_refs,
};
}
return null;
},
markdownPreviewPath() {
const notable = this.getNoteableDataByProp('preview_note_path');
return mergeUrlParams({ preview_suggestions: true }, notable);
const previewSuggestions = this.line && this.diffParams;
const params = previewSuggestions
? {
preview_suggestions: previewSuggestions,
line: this.line.new_line,
file_path: this.diffParams.filePath,
base_sha: this.diffParams.refs.base_sha,
start_sha: this.diffParams.refs.start_sha,
head_sha: this.diffParams.refs.head_sha,
}
: {};
return mergeUrlParams(params, notable);
},
markdownDocsPath() {
return this.getNotesDataByProp('markdownDocsPath');
Loading
Loading
@@ -234,8 +272,8 @@ export default {
placeholder="Write a comment or drag your files here…"
@keydown.meta.enter="handleKeySubmit()"
@keydown.ctrl.enter="handleKeySubmit()"
@keydown.up="editMyLastNote()"
@keydown.esc="cancelHandler(true)"
@keydown.exact.up="editMyLastNote()"
@keydown.exact.esc="cancelHandler(true)"
@input="onInput"
></textarea>
</markdown-field>
Loading
Loading
/* eslint-disable import/prefer-default-export */
function trimFirstCharOfLineContent(text) {
if (!text) {
return text;
}
return text.replace(/^( |\+|-)/, '');
}
function cleanSuggestionLine(line = {}) {
return {
...line,
text: trimFirstCharOfLineContent(line.text),
};
}
export function selectDiffLines(lines) {
return lines.filter(line => line.type !== 'match').map(line => cleanSuggestionLine(line));
}
Loading
Loading
@@ -76,6 +76,7 @@ export default {
hasSuggestion: false,
markdownPreviewLoading: false,
previewMarkdown: false,
suggestions: this.note.suggestions || [],
};
},
computed: {
Loading
Loading
@@ -109,9 +110,6 @@ export default {
}
return lineNumber;
},
suggestions() {
return this.note.suggestions || [];
},
lineType() {
return this.line ? this.line.type : '';
},
Loading
Loading
@@ -175,6 +173,7 @@ export default {
this.referencedCommands = data.references.commands;
this.referencedUsers = data.references.users;
this.hasSuggestion = data.references.suggestions && data.references.suggestions.length;
this.suggestions = data.references.suggestions;
}
 
this.$nextTick()
Loading
Loading
Loading
Loading
@@ -38,7 +38,7 @@ export default {
].join('\n');
},
mdSuggestion() {
return ['```suggestion', `{text}`, '```'].join('\n');
return ['```suggestion:-0+0', `{text}`, '```'].join('\n');
},
},
mounted() {
Loading
Loading
<script>
import SuggestionDiffHeader from './suggestion_diff_header.vue';
import SuggestionDiffRow from './suggestion_diff_row.vue';
import { selectDiffLines } from '../lib/utils/diff_utils';
 
export default {
components: {
SuggestionDiffHeader,
SuggestionDiffRow,
},
props: {
newLines: {
type: Array,
required: true,
},
fromContent: {
type: String,
required: false,
default: '',
},
fromLine: {
type: Number,
required: true,
},
suggestion: {
type: Object,
required: true,
Loading
Loading
@@ -33,6 +23,11 @@ export default {
required: true,
},
},
computed: {
lines() {
return selectDiffLines(this.suggestion.diff_lines);
},
},
methods: {
applySuggestion(callback) {
this.$emit('apply', { suggestionId: this.suggestion.id, callback });
Loading
Loading
@@ -52,22 +47,11 @@ export default {
/>
<table class="mb-3 md-suggestion-diff js-syntax-highlight code">
<tbody>
<!-- Old Line -->
<tr class="line_holder old">
<td class="diff-line-num old_line qa-old-diff-line-number old">{{ fromLine }}</td>
<td class="diff-line-num new_line old"></td>
<td class="line_content old">
<span>{{ fromContent }}</span>
</td>
</tr>
<!-- New Line(s) -->
<tr v-for="(line, key) of newLines" :key="key" class="line_holder new">
<td class="diff-line-num old_line new"></td>
<td class="diff-line-num new_line qa-new-diff-line-number new">{{ line.lineNumber }}</td>
<td class="line_content new">
<span>{{ line.content }}</span>
</td>
</tr>
<suggestion-diff-row
v-for="(line, index) of lines"
:key="`${index}-${line.text}`"
:line="line"
/>
</tbody>
</table>
</div>
Loading
Loading
<script>
export default {
name: 'SuggestionDiffRow',
props: {
line: {
type: Object,
required: true,
},
},
computed: {
lineType() {
return this.line.type;
},
},
};
</script>
<template>
<tr class="line_holder" :class="lineType">
<td class="diff-line-num old_line" :class="lineType">
{{ line.old_line }}
</td>
<td class="diff-line-num new_line" :class="lineType">
{{ line.new_line }}
</td>
<td class="line_content" :class="lineType">
<span v-if="line.text">{{ line.text }}</span>
<!-- TODO: replace this hack with zero-width whitespace when we have rich_text from BE -->
<span v-else>&#8203;</span>
</td>
</tr>
</template>
Loading
Loading
@@ -6,16 +6,6 @@ import Flash from '~/flash';
export default {
components: { SuggestionDiff },
props: {
fromLine: {
type: Number,
required: false,
default: 0,
},
fromContent: {
type: String,
required: false,
default: '',
},
lineType: {
type: String,
required: false,
Loading
Loading
@@ -71,41 +61,19 @@ export default {
 
suggestionElements.forEach((suggestionEl, i) => {
const suggestionParentEl = suggestionEl.parentElement;
const newLines = this.extractNewLines(suggestionParentEl);
const diffComponent = this.generateDiff(newLines, i);
const diffComponent = this.generateDiff(i);
diffComponent.$mount(suggestionParentEl);
});
 
this.isRendered = true;
},
extractNewLines(suggestionEl) {
// extracts the suggested lines from the markdown
// calculates a line number for each line
const newLines = suggestionEl.querySelectorAll('.line');
const fromLine = this.suggestions.length ? this.suggestions[0].from_line : this.fromLine;
const lines = [];
newLines.forEach((line, i) => {
const content = `${line.innerText}\n`;
const lineNumber = fromLine + i;
lines.push({ content, lineNumber });
});
return lines;
},
generateDiff(newLines, suggestionIndex) {
// generates the diff <suggestion-diff /> component
// all `suggestion` markdown will be swapped out by this component
generateDiff(suggestionIndex) {
const { suggestions, disabled, helpPagePath } = this;
const suggestion =
suggestions && suggestions[suggestionIndex] ? suggestions[suggestionIndex] : {};
const fromContent = suggestion.from_content || this.fromContent;
const fromLine = suggestion.from_line || this.fromLine;
const SuggestionDiffComponent = Vue.extend(SuggestionDiff);
const suggestionDiff = new SuggestionDiffComponent({
propsData: { newLines, fromLine, fromContent, disabled, suggestion, helpPagePath },
propsData: { disabled, suggestion, helpPagePath },
});
 
suggestionDiff.$on('apply', ({ suggestionId, callback }) => {
Loading
Loading
Loading
Loading
@@ -44,7 +44,6 @@ $note-form-margin-left: 72px;
border: 1px solid $border-color;
border-radius: $border-radius-default;
margin: $gl-padding 0;
overflow: auto;
 
&.system-note,
&.note-form {
Loading
Loading
Loading
Loading
@@ -20,7 +20,7 @@ module PreviewMarkdown
body: view_context.markdown(result[:text], markdown_params),
references: {
users: result[:users],
suggestions: result[:suggestions],
suggestions: SuggestionSerializer.new.represent_diff(result[:suggestions]),
commands: view_context.markdown(result[:commands])
}
}
Loading
Loading
Loading
Loading
@@ -5,6 +5,7 @@ class GitlabSchema < GraphQL::Schema
use Gitlab::Graphql::Authorize
use Gitlab::Graphql::Present
use Gitlab::Graphql::Connections
use Gitlab::Graphql::Tracing
 
query(Types::QueryType)
 
Loading
Loading
Loading
Loading
@@ -228,22 +228,21 @@ class Group < Namespace
def has_owner?(user)
return false unless user
 
members_with_parents.owners.where(user_id: user).any?
members_with_parents.owners.exists?(user_id: user)
end
 
def has_maintainer?(user)
return false unless user
 
members_with_parents.maintainers.where(user_id: user).any?
members_with_parents.maintainers.exists?(user_id: user)
end
 
# @deprecated
alias_method :has_master?, :has_maintainer?
 
# Check if user is a last owner of the group.
# Parent owners are ignored for nested groups.
def last_owner?(user)
owners.include?(user) && owners.size == 1
has_owner?(user) && members_with_parents.owners.size == 1
end
 
def ldap_synced?
Loading
Loading
Loading
Loading
@@ -42,6 +42,6 @@ class IssueEntity < IssuableEntity
end
 
expose :preview_note_path do |issue|
preview_markdown_path(issue.project, quick_actions_target_type: 'Issue', quick_actions_target_id: issue.iid)
preview_markdown_path(issue.project, target_type: 'Issue', target_id: issue.iid)
end
end
Loading
Loading
@@ -235,7 +235,7 @@ class MergeRequestWidgetEntity < IssuableEntity
end
 
expose :preview_note_path do |merge_request|
preview_markdown_path(merge_request.project, quick_actions_target_type: 'MergeRequest', quick_actions_target_id: merge_request.iid)
preview_markdown_path(merge_request.project, target_type: 'MergeRequest', target_id: merge_request.iid)
end
 
expose :merge_commit_path do |merge_request|
Loading
Loading
Loading
Loading
@@ -3,6 +3,8 @@
class SuggestionEntity < API::Entities::Suggestion
include RequestAwareEntity
 
unexpose :from_line, :to_line, :from_content, :to_content
expose :diff_lines, using: DiffLineEntity
expose :current_user do
expose :can_apply do |suggestion|
Ability.allowed?(current_user, :apply_suggestion, suggestion)
Loading
Loading
# frozen_string_literal: true
class SuggestionSerializer < BaseSerializer
entity SuggestionEntity
def represent_diff(resource)
represent(resource, { only: [:diff_lines] })
end
end
Loading
Loading
@@ -2,10 +2,17 @@
 
module Suggestible
extend ActiveSupport::Concern
include Gitlab::Utils::StrongMemoize
 
# This translates into limiting suggestion changes to `suggestion:-100+100`.
MAX_LINES_CONTEXT = 100.freeze
 
def diff_lines
strong_memoize(:diff_lines) do
Gitlab::Diff::SuggestionDiff.new(self).diff_lines
end
end
def fetch_from_content
diff_file.new_blob_lines_between(from_line, to_line).join
end
Loading
Loading
Loading
Loading
@@ -17,7 +17,7 @@ class PreviewMarkdownService < BaseService
private
 
def explain_quick_actions(text)
return text, [] unless %w(Issue MergeRequest Commit).include?(commands_target_type)
return text, [] unless %w(Issue MergeRequest Commit).include?(target_type)
 
quick_actions_service = QuickActions::InterpretService.new(project, current_user)
quick_actions_service.explain(text, find_commands_target)
Loading
Loading
@@ -30,22 +30,34 @@ class PreviewMarkdownService < BaseService
end
 
def find_suggestions(text)
return [] unless params[:preview_suggestions]
return [] unless preview_sugestions?
 
Banzai::SuggestionsParser.parse(text)
position = Gitlab::Diff::Position.new(new_path: params[:file_path],
new_line: params[:line].to_i,
base_sha: params[:base_sha],
head_sha: params[:head_sha],
start_sha: params[:start_sha])
Gitlab::Diff::SuggestionsParser.parse(text, position: position, project: project)
end
def preview_sugestions?
params[:preview_suggestions] &&
target_type == 'MergeRequest' &&
Ability.allowed?(current_user, :download_code, project)
end
 
def find_commands_target
QuickActions::TargetService
.new(project, current_user)
.execute(commands_target_type, commands_target_id)
.execute(target_type, target_id)
end
 
def commands_target_type
params[:quick_actions_target_type]
def target_type
params[:target_type]
end
 
def commands_target_id
params[:quick_actions_target_id]
def target_id
params[:target_id]
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment