summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjerasmus <jerasmus@gitlab.com>2018-11-21 16:47:57 +0200
committerjerasmus <jerasmus@gitlab.com>2018-11-21 16:47:57 +0200
commite89d8b485c7ece09534168c13a3fb55c0a1cb20f (patch)
tree4bade7b0d919ad30c25043582a064e9ec61ebdb7
parentbd082c69d2be456ef19f992066796cd7c8bd4d1c (diff)
downloadgitlab-ce-suggest-change-to-diff-line-fe.tar.gz
Add toolbar icon + UX adjustmentssuggest-change-to-diff-line-fe
Added MD toolbar icon. Refined the UI to match ux mockups.
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_comment_row.vue6
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js14
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue34
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue33
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue6
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss7
11 files changed, 115 insertions, 11 deletions
diff --git a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
index 91b87fb042c..712acdcca85 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
@@ -37,7 +37,11 @@ export default {
<tr :class="className" class="notes_holder">
<td class="notes_content" colspan="3">
<div class="content">
- <diff-discussions v-if="line.discussions.length" :discussions="line.discussions" />
+ <diff-discussions
+ v-if="line.discussions.length"
+ :line="line"
+ :discussions="line.discussions"
+ />
<diff-line-note-form
v-if="diffLineCommentForms[line.line_code]"
:diff-file-hash="diffFileHash"
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 3618c6af7e2..dec85dc1da8 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -39,7 +39,7 @@ function blockTagText(text, textArea, blockTag, selected) {
}
}
-function moveCursor({ textArea, tag, positionBetweenTags, removedLastNewLine, select }) {
+function moveCursor({ textArea, tag, cursorOffset, positionBetweenTags, removedLastNewLine, select }) {
var pos;
if (!textArea.setSelectionRange) {
return;
@@ -61,11 +61,15 @@ function moveCursor({ textArea, tag, positionBetweenTags, removedLastNewLine, se
pos -= 1;
}
+ if(cursorOffset) {
+ pos -= cursorOffset;
+ }
+
return textArea.setSelectionRange(pos, pos);
}
}
-export function insertMarkdownText({ textArea, text, tag, blockTag, selected, wrap, select }) {
+export function insertMarkdownText({ textArea, text, tag, cursorOffset, blockTag, selected, wrap, select }) {
var textToInsert,
selectedSplit,
startChar,
@@ -154,20 +158,21 @@ export function insertMarkdownText({ textArea, text, tag, blockTag, selected, wr
return moveCursor({
textArea,
tag: tag.replace(textPlaceholder, selected),
+ cursorOffset,
positionBetweenTags: wrap && selected.length === 0,
removedLastNewLine,
select,
});
}
-function updateText({ textArea, tag, blockTag, wrap, select }) {
+function updateText({ textArea, tag, cursorOffset, blockTag, wrap, select }) {
var $textArea, selected, text;
$textArea = $(textArea);
textArea = $textArea.get(0);
text = $textArea.val();
selected = selectedText(text, textArea);
$textArea.focus();
- return insertMarkdownText({ textArea, text, tag, blockTag, selected, wrap, select });
+ return insertMarkdownText({ textArea, text, tag, cursorOffset, blockTag, selected, wrap, select });
}
export function addMarkdownListeners(form) {
@@ -178,6 +183,7 @@ export function addMarkdownListeners(form) {
return updateText({
textArea: $this.closest('.md-area').find('textarea'),
tag: $this.data('mdTag'),
+ cursorOffset: $this.data('mdCursorOffset'),
blockTag: $this.data('mdBlock'),
wrap: !$this.data('mdPrepend'),
select: $this.data('mdSelect'),
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index c0bee600181..c0bce9bcd65 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -5,6 +5,7 @@ import noteAwardsList from './note_awards_list.vue';
import noteAttachment from './note_attachment.vue';
import noteForm from './note_form.vue';
import autosave from '../mixins/autosave';
+import suggestion from '~/vue_shared/components/markdown/suggestion.vue';
export default {
components: {
@@ -12,6 +13,7 @@ export default {
noteAwardsList,
noteAttachment,
noteForm,
+ suggestion,
},
mixins: [autosave],
props: {
@@ -19,6 +21,11 @@ export default {
type: Object,
required: true,
},
+ line: {
+ type: Object,
+ required: false,
+ default: null,
+ },
canEdit: {
type: Boolean,
required: true,
@@ -33,6 +40,21 @@ export default {
noteBody() {
return this.note.note;
},
+ mockSuggestion() {
+ // temporary: this will be generated on the backend and returned via api call in parent
+ return `
+ <p dir="auto">I suggest</p>
+ &#x000A;
+ <pre class="code highlight js-syntax-highlight suggestion" lang="suggestion" v-pre="true"><code class="js-render-suggestion"><span id="LC1" class="line" lang="suggestion">&lt;p&gt;Foo&lt;/p&gt;</span></code></pre>
+ &#x000A;
+
+ <p dir="auto">Or this</p>
+ &#x000A;
+ <pre class="code highlight js-syntax-highlight suggestion" lang="suggestion" v-pre="true"><code class="js-render-suggestion"><span id="LC1" class="line" lang="suggestion">&lt;p&gt;Bar&lt;/p&gt;</span></code></pre>`;
+ },
+ isSuggestion() {
+ return this.mockSuggestion.includes('js-render-suggestion');
+ },
},
mounted() {
this.renderGFM();
@@ -68,7 +90,17 @@ export default {
<template>
<div ref="note-body" :class="{ 'js-task-list-container': canEdit }" class="note-body">
- <div class="note-text md" v-html="note.note_html"></div>
+ <suggestion
+ v-if="isSuggestion"
+ :note="note"
+ :line="line"
+ :suggestion-html="mockSuggestion"
+ />
+ <div
+ v-else
+ class="note-text md"
+ v-html="mockSuggestion"
+ ></div>
<note-form
v-if="isEditing"
ref="noteForm"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index ad58267b533..fed5e2400b3 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -48,6 +48,11 @@ export default {
required: false,
default: '',
},
+ line: {
+ type: Object,
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -166,6 +171,7 @@ export default {
:markdown-version="markdownVersion"
:quick-actions-docs-path="quickActionsDocsPath"
:add-spacing-classes="false"
+ :line="line"
>
<textarea
id="note_note"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index 21d6519191f..392c08fc5c0 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -6,12 +6,14 @@ import GLForm from '../../../gl_form';
import markdownHeader from './header.vue';
import markdownToolbar from './toolbar.vue';
import icon from '../icon.vue';
+import suggestion from '~/vue_shared/components/markdown/suggestion.vue';
export default {
components: {
markdownHeader,
markdownToolbar,
icon,
+ suggestion,
},
props: {
markdownPreviewPath: {
@@ -48,6 +50,11 @@ export default {
required: false,
default: true,
},
+ line: {
+ type: Object,
+ required: false,
+ default: null,
+ },
},
data() {
return {
@@ -63,6 +70,21 @@ export default {
const referencedUsersThreshold = 10;
return this.referencedUsers.length >= referencedUsersThreshold;
},
+ mockSuggestion() {
+ // temporary: this will be generated on the backend and returned via api call in parent
+ return `
+ <p dir="auto">I suggest</p>
+ &#x000A;
+ <pre class="code highlight js-syntax-highlight suggestion" lang="suggestion" v-pre="true"><code class="js-render-suggestion"><span id="LC1" class="line" lang="suggestion">&lt;p&gt;Foo&lt;/p&gt;</span></code></pre>
+ &#x000A;
+
+ <p dir="auto">Or this</p>
+ &#x000A;
+ <pre class="code highlight js-syntax-highlight suggestion" lang="suggestion" v-pre="true"><code class="js-render-suggestion"><span id="LC1" class="line" lang="suggestion">&lt;p&gt;Bar&lt;/p&gt;</span></code></pre>`;
+ },
+ isSuggestion() {
+ return this.mockSuggestion.includes('js-render-suggestion');
+ },
},
mounted() {
/*
@@ -163,7 +185,16 @@ export default {
</div>
</div>
<div v-show="previewMarkdown" class="md md-preview-holder md-preview js-vue-md-preview">
- <div ref="markdown-preview" v-html="markdownPreview"></div>
+ <suggestion
+ v-if="isSuggestion"
+ :suggestion-html="mockSuggestion"
+ :line="line"
+ />
+ <div
+ v-else
+ ref="markdown-preview"
+ v-html="mockSuggestion"
+ ></div>
<span v-if="markdownPreviewLoading"> Loading... </span>
</div>
<template v-if="previewMarkdown && !markdownPreviewLoading">
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 4c4ba537065..8c68a9d5be6 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -119,6 +119,13 @@ export default {
:button-title="__('Add a table')"
icon="table"
/>
+ <toolbar-button
+ tag="```suggestion {text} ```"
+ :prepend="true"
+ :button-title="__('Insert suggestion')"
+ :cursor-offset="4"
+ icon="doc-code"
+ />
<button
v-gl-tooltip
aria-label="Go full screen"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion.vue
index d6b0ce2ea9c..18cba8aab39 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion.vue
@@ -102,7 +102,6 @@ export default {
<div>
<div
ref="container"
- class="md-suggestion-diff"
v-html="suggestionHtml"
></div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
index 6a2a7adb314..7b30053508f 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue
@@ -29,12 +29,12 @@ export default {
</script>
<template>
- <div class="md-suggestion-diff-content">
+ <div>
<suggestion-diff-header
:can-apply="canApply"
@apply="applySuggestion"
/>
- <table class="mb-3">
+ <table class="mb-3 md-suggestion-diff">
<tbody>
<!-- New Line -->
<tr class="line_holder new">
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
index ddb303b8962..463fc39b5ff 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff_header.vue
@@ -1,5 +1,8 @@
<script>
+import Icon from '~/vue_shared/components/icon.vue';
+
export default {
+ components: { Icon },
props: {
canApply: {
type: Boolean,
@@ -17,7 +20,10 @@ export default {
<template>
<div class="file-title-flex-parent md-suggestion-header border-bottom-0 mt-2">
- Suggested change
+ <div>
+ Suggested change
+ <icon name="question-o" css-classes="link-highlight" />
+ </div>
<button
v-if="canApply"
type="button"
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
index a6d2cecdf7e..4bf6a0b9b26 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
@@ -37,6 +37,11 @@ export default {
required: false,
default: false,
},
+ cursorOffset: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
},
};
</script>
@@ -45,6 +50,7 @@ export default {
<button
v-gl-tooltip
:data-md-tag="tag"
+ :data-md-cursor-offset="cursorOffset"
:data-md-select="tagSelect"
:data-md-block="tagBlock"
:data-md-prepend="prepend"
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index 6ef3d700015..e83af08f478 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -265,10 +265,17 @@
}
}
+.md-suggestion-diff {
+ border: 1px solid $border-color !important;
+}
+
.md-suggestion-header {
border: 1px solid $border-color;
font-weight: $gl-font-weight-bold;
height: 45px;
+ svg {
+ color: $blue-600;
+ }
}
@include media-breakpoint-down(xs) {